From: Nipun Gupta <nipun.gupta@amd.com>
To: <robh+dt@kernel.org>, <krzysztof.kozlowski+dt@linaro.org>,
<gregkh@linuxfoundation.org>, <rafael@kernel.org>,
<eric.auger@redhat.com>, <alex.williamson@redhat.com>,
<cohuck@redhat.com>, <song.bao.hua@hisilicon.com>,
<mchehab+huawei@kernel.org>, <maz@kernel.org>,
<f.fainelli@gmail.com>, <jeffrey.l.hugo@gmail.com>,
<saravanak@google.com>, <Michael.Srba@seznam.cz>,
<mani@kernel.org>, <yishaih@nvidia.com>, <jgg@ziepe.ca>,
<jgg@nvidia.com>, <robin.murphy@arm.com>, <will@kernel.org>,
<joro@8bytes.org>, <masahiroy@kernel.org>,
<ndesaulniers@google.com>, <linux-arm-kernel@lists.infradead.org>,
<linux-kbuild@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<devicetree@vger.kernel.org>
Cc: <okaya@kernel.org>, <harpreet.anand@amd.com>,
<nikhil.agarwal@amd.com>, <michal.simek@amd.com>, <git@amd.com>,
Abhijit Gangurde <abhijit.gangurde@amd.com>,
Nipun Gupta <nipun.gupta@amd.com>
Subject: [PATCH 06/19] bus/cdx: add rpmsg communication channel for CDX
Date: Tue, 17 Jan 2023 19:11:38 +0530 [thread overview]
Message-ID: <20230117134139.1298-7-nipun.gupta@amd.com> (raw)
In-Reply-To: <20230117134139.1298-1-nipun.gupta@amd.com>
From: Abhijit Gangurde <abhijit.gangurde@amd.com>
RPMsg is used as a transport communication channel. This
change introduces RPMsg driver and integrates it with the
CDX controller.
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
Signed-off-by: Nipun Gupta <nipun.gupta@amd.com>
---
drivers/bus/cdx/controller/Kconfig | 1 +
drivers/bus/cdx/controller/Makefile | 2 +-
drivers/bus/cdx/controller/cdx_controller.c | 36 +++-
drivers/bus/cdx/controller/cdx_controller.h | 30 +++
drivers/bus/cdx/controller/cdx_rpmsg.c | 222 ++++++++++++++++++++
drivers/bus/cdx/controller/mcdi.h | 9 +
6 files changed, 291 insertions(+), 9 deletions(-)
create mode 100644 drivers/bus/cdx/controller/cdx_controller.h
create mode 100644 drivers/bus/cdx/controller/cdx_rpmsg.c
diff --git a/drivers/bus/cdx/controller/Kconfig b/drivers/bus/cdx/controller/Kconfig
index 17f9c6be2fe1..aea3ac86d3aa 100644
--- a/drivers/bus/cdx/controller/Kconfig
+++ b/drivers/bus/cdx/controller/Kconfig
@@ -9,6 +9,7 @@ if CDX_BUS
config CDX_CONTROLLER
tristate "CDX bus controller"
+ select RPMSG
help
CDX controller drives the CDX bus. It interacts with
firmware to get the hardware devices and registers with
diff --git a/drivers/bus/cdx/controller/Makefile b/drivers/bus/cdx/controller/Makefile
index f7437c882cc9..f071be411d96 100644
--- a/drivers/bus/cdx/controller/Makefile
+++ b/drivers/bus/cdx/controller/Makefile
@@ -6,4 +6,4 @@
#
obj-$(CONFIG_CDX_CONTROLLER) += cdx-controller.o
-cdx-controller-objs := cdx_controller.o mcdi.o mcdi_functions.o
+cdx-controller-objs := cdx_controller.o cdx_rpmsg.o mcdi.o mcdi_functions.o
diff --git a/drivers/bus/cdx/controller/cdx_controller.c b/drivers/bus/cdx/controller/cdx_controller.c
index 9b910c9cb31e..b62a6d3b7bd4 100644
--- a/drivers/bus/cdx/controller/cdx_controller.c
+++ b/drivers/bus/cdx/controller/cdx_controller.c
@@ -8,6 +8,7 @@
#include <linux/of_platform.h>
#include <linux/cdx/cdx_bus.h>
+#include "cdx_controller.h"
#include "../cdx.h"
#include "mcdi_functions.h"
#include "mcdi.h"
@@ -53,20 +54,14 @@ static void cdx_mcdi_request(struct cdx_mcdi *cdx, u8 bufid,
const struct cdx_dword *hdr, size_t hdr_len,
const struct cdx_dword *sdu, size_t sdu_len)
{
- /*
- * This will get updated by rpmsg APIs, with RPMSG introduction
- * in CDX controller as a transport layer.
- */
+ cdx_rpmsg_send(cdx, hdr, hdr_len, sdu, sdu_len);
}
static void cdx_mcdi_read_response(struct cdx_mcdi *cdx_mcdi, u8 bufid,
struct cdx_dword *outbuf, size_t offset,
size_t outlen)
{
- /*
- * This will get updated by rpmsg APIs, with RPMSG introduction
- * in CDX controller as a transport layer.
- */
+ cdx_rpmsg_read_resp(cdx_mcdi, outbuf, offset, outlen);
}
static const struct cdx_mcdi_ops mcdi_ops = {
@@ -77,6 +72,19 @@ static const struct cdx_mcdi_ops mcdi_ops = {
.mcdi_put_buf = cdx_mcdi_put_buf,
};
+void cdx_rpmsg_post_probe(struct cdx_controller *cdx)
+{
+ /* Register CDX controller with CDX bus driver */
+ if (cdx_register_controller(cdx))
+ dev_err(cdx->dev, "Failed to register CDX controller\n");
+}
+
+void cdx_rpmsg_pre_remove(struct cdx_controller *cdx)
+{
+ cdx_unregister_controller(cdx);
+ cdx_mcdi_wait_for_quiescence(cdx->priv, MCDI_RPC_TIMEOUT);
+}
+
static int cdx_scan_devices(struct cdx_controller *cdx)
{
struct cdx_mcdi *cdx_mcdi = cdx->priv;
@@ -174,9 +182,19 @@ static int xlnx_cdx_probe(struct platform_device *pdev)
goto cdx_mcdi_buf_fail;
}
+ ret = cdx_setup_rpmsg(pdev);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to register CDX RPMsg transport\n");
+ goto cdx_rpmsg_fail;
+ }
+
dev_info(&pdev->dev, "Successfully registered CDX controller with RPMsg as transport\n");
return 0;
+cdx_rpmsg_fail:
+ kfree(cdx_mcdi->mcdi_buf);
+ cdx_mcdi->mcdi_buf = NULL;
cdx_mcdi_buf_fail:
kfree(cdx);
cdx_alloc_fail:
@@ -192,6 +210,8 @@ static int xlnx_cdx_remove(struct platform_device *pdev)
struct cdx_controller *cdx = platform_get_drvdata(pdev);
struct cdx_mcdi *cdx_mcdi = cdx->priv;
+ cdx_destroy_rpmsg(pdev);
+
kfree(cdx_mcdi->mcdi_buf);
kfree(cdx);
diff --git a/drivers/bus/cdx/controller/cdx_controller.h b/drivers/bus/cdx/controller/cdx_controller.h
new file mode 100644
index 000000000000..43b7c742df87
--- /dev/null
+++ b/drivers/bus/cdx/controller/cdx_controller.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Header file for the CDX Controller
+ *
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+ */
+
+#ifndef _CDX_CONTROLLER_H_
+#define _CDX_CONTROLLER_H_
+
+#include <linux/cdx/cdx_bus.h>
+#include "mcdi_functions.h"
+
+void cdx_rpmsg_post_probe(struct cdx_controller *cdx);
+
+void cdx_rpmsg_pre_remove(struct cdx_controller *cdx);
+
+int cdx_rpmsg_send(struct cdx_mcdi *cdx_mcdi,
+ const struct cdx_dword *hdr, size_t hdr_len,
+ const struct cdx_dword *sdu, size_t sdu_len);
+
+void cdx_rpmsg_read_resp(struct cdx_mcdi *cdx_mcdi,
+ struct cdx_dword *outbuf, size_t offset,
+ size_t outlen);
+
+int cdx_setup_rpmsg(struct platform_device *pdev);
+
+void cdx_destroy_rpmsg(struct platform_device *pdev);
+
+#endif /* _CDX_CONT_PRIV_H_ */
diff --git a/drivers/bus/cdx/controller/cdx_rpmsg.c b/drivers/bus/cdx/controller/cdx_rpmsg.c
new file mode 100644
index 000000000000..147c2fadf67f
--- /dev/null
+++ b/drivers/bus/cdx/controller/cdx_rpmsg.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Platform driver for CDX bus.
+ *
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+ */
+
+#include <linux/rpmsg.h>
+#include <linux/remoteproc.h>
+#include <linux/of_platform.h>
+#include <linux/cdx/cdx_bus.h>
+#include <linux/module.h>
+
+#include "../cdx.h"
+#include "cdx_controller.h"
+#include "mcdi_functions.h"
+#include "mcdi.h"
+
+#define to_rproc_device(_dev) \
+ container_of(_dev, struct rproc, dev)
+
+static struct rpmsg_device_id cdx_rpmsg_id_table[] = {
+ { .name = "mcdi_ipc" },
+ { },
+};
+MODULE_DEVICE_TABLE(rpmsg, cdx_rpmsg_id_table);
+
+int cdx_rpmsg_send(struct cdx_mcdi *cdx_mcdi,
+ const struct cdx_dword *hdr, size_t hdr_len,
+ const struct cdx_dword *sdu, size_t sdu_len)
+{
+ char send_buf[MCDI_BUF_LEN] = {0};
+
+ memset(cdx_mcdi->mcdi_buf, 0x0, MCDI_BUF_LEN);
+
+ memcpy(send_buf, hdr, hdr_len);
+ memcpy(send_buf + hdr_len, sdu, sdu_len);
+
+ return rpmsg_send(cdx_mcdi->ept, send_buf, hdr_len + sdu_len);
+}
+
+void cdx_rpmsg_read_resp(struct cdx_mcdi *cdx_mcdi,
+ struct cdx_dword *outbuf, size_t offset,
+ size_t outlen)
+{
+ memcpy(outbuf, (void *)((u64)cdx_mcdi->mcdi_buf + offset), outlen);
+}
+
+static int find_remoteproc_child_dev(struct device *dev, void *data)
+{
+ return strstr(dev_name(dev), "remoteproc") ? 1 : 0;
+}
+
+static int cdx_attach_to_rproc(struct platform_device *pdev)
+{
+ struct platform_device *node_pdev;
+ struct device_node *r5_core_node;
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+ struct device *dev;
+ struct rproc *rp;
+ int ret;
+
+ dev = &pdev->dev;
+ cdx_c = platform_get_drvdata(pdev);
+ cdx_mcdi = cdx_c->priv;
+
+ r5_core_node = of_parse_phandle(dev->of_node, "xlnx,rproc", 0);
+ if (!r5_core_node) {
+ dev_err(&pdev->dev, "xlnx,rproc: invalid phandle\n");
+ return -EINVAL;
+ }
+
+ node_pdev = of_find_device_by_node(r5_core_node);
+ if (!node_pdev) {
+ ret = -EPROBE_DEFER;
+ goto pdev_err;
+ }
+
+ dev = device_find_child(&node_pdev->dev, NULL, find_remoteproc_child_dev);
+ if (!dev) {
+ dev_err(&pdev->dev, "no matching remoteproc device found\n");
+ ret = -ENODEV;
+ goto no_child_err;
+ }
+
+ rp = to_rproc_device(dev);
+
+ /* Attach to remote processor */
+ ret = rproc_boot(rp);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to attach to remote processor\n");
+ goto no_child_err;
+ }
+
+ cdx_mcdi->r5_rproc = rp;
+no_child_err:
+ put_device(&node_pdev->dev);
+pdev_err:
+ of_node_put(r5_core_node);
+ return ret;
+}
+
+static void cdx_detach_to_r5(struct platform_device *pdev)
+{
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+
+ cdx_c = platform_get_drvdata(pdev);
+ cdx_mcdi = cdx_c->priv;
+
+ rproc_detach(cdx_mcdi->r5_rproc);
+}
+
+static int cdx_rpmsg_cb(struct rpmsg_device *rpdev, void *data,
+ int len, void *priv, u32 src)
+{
+ struct cdx_controller *cdx_c = dev_get_drvdata(&rpdev->dev);
+ struct cdx_mcdi *cdx_mcdi = cdx_c->priv;
+
+ if (len > MCDI_BUF_LEN)
+ return -EINVAL;
+
+ memcpy(cdx_mcdi->mcdi_buf, data, len);
+ cdx_mcdi_process_cmd(cdx_mcdi, *(struct cdx_dword *)cdx_mcdi->mcdi_buf);
+
+ return 0;
+}
+
+static void cdx_rpmsg_post_probe_work(struct work_struct *work)
+{
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+
+ cdx_mcdi = container_of(work, struct cdx_mcdi, work);
+ cdx_c = dev_get_drvdata(&cdx_mcdi->rpdev->dev);
+ cdx_rpmsg_post_probe(cdx_c);
+}
+
+static int cdx_rpmsg_probe(struct rpmsg_device *rpdev)
+{
+ struct rpmsg_channel_info chinfo = {0};
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+
+ cdx_c = (struct cdx_controller *)cdx_rpmsg_id_table[0].driver_data;
+ cdx_mcdi = cdx_c->priv;
+
+ chinfo.src = RPMSG_ADDR_ANY;
+ chinfo.dst = rpdev->dst;
+ strscpy(chinfo.name, cdx_rpmsg_id_table[0].name,
+ strlen(cdx_rpmsg_id_table[0].name));
+
+ cdx_mcdi->ept = rpmsg_create_ept(rpdev, cdx_rpmsg_cb, NULL, chinfo);
+ if (!cdx_mcdi->ept) {
+ dev_err_probe(&rpdev->dev, -ENXIO,
+ "Failed to create ept for channel %s\n",
+ chinfo.name);
+ return -EINVAL;
+ }
+
+ cdx_mcdi->rpdev = rpdev;
+ dev_set_drvdata(&rpdev->dev, cdx_c);
+
+ schedule_work(&cdx_mcdi->work);
+ return 0;
+}
+
+static void cdx_rpmsg_remove(struct rpmsg_device *rpdev)
+{
+ struct cdx_controller *cdx_c = dev_get_drvdata(&rpdev->dev);
+ struct cdx_mcdi *cdx_mcdi = cdx_c->priv;
+
+ flush_work(&cdx_mcdi->work);
+ cdx_rpmsg_pre_remove(cdx_c);
+
+ rpmsg_destroy_ept(cdx_mcdi->ept);
+ dev_set_drvdata(&rpdev->dev, NULL);
+}
+
+static struct rpmsg_driver cdx_rpmsg_driver = {
+ .drv.name = KBUILD_MODNAME,
+ .id_table = cdx_rpmsg_id_table,
+ .probe = cdx_rpmsg_probe,
+ .remove = cdx_rpmsg_remove,
+ .callback = cdx_rpmsg_cb,
+};
+
+int cdx_setup_rpmsg(struct platform_device *pdev)
+{
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+ int ret;
+
+ /* Attach to remote processor */
+ ret = cdx_attach_to_rproc(pdev);
+ if (ret)
+ return ret;
+
+ cdx_c = platform_get_drvdata(pdev);
+ cdx_mcdi = cdx_c->priv;
+
+ /* Register RPMsg driver */
+ cdx_rpmsg_id_table[0].driver_data = (kernel_ulong_t)cdx_c;
+
+ INIT_WORK(&cdx_mcdi->work, cdx_rpmsg_post_probe_work);
+ ret = register_rpmsg_driver(&cdx_rpmsg_driver);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Failed to register cdx RPMsg driver: %d\n", ret);
+ cdx_detach_to_r5(pdev);
+ }
+
+ return ret;
+}
+
+void cdx_destroy_rpmsg(struct platform_device *pdev)
+{
+ unregister_rpmsg_driver(&cdx_rpmsg_driver);
+
+ cdx_detach_to_r5(pdev);
+}
diff --git a/drivers/bus/cdx/controller/mcdi.h b/drivers/bus/cdx/controller/mcdi.h
index a2ee8821b6fe..54e1b27c2a53 100644
--- a/drivers/bus/cdx/controller/mcdi.h
+++ b/drivers/bus/cdx/controller/mcdi.h
@@ -64,6 +64,10 @@ enum cdx_mcdi_cmd_state {
* @mcdi_buf_use: Stores MCDI buffer usage
* @mcdi_ops: MCDI operations
* @mcdi_buf: MCDI receive buffer
+ * @r5_rproc : R5 Remoteproc device handle
+ * @rpdev: RPMsg device
+ * @ept: RPMsg endpoint
+ * @work: Post probe work
*/
struct cdx_mcdi {
/* MCDI interface */
@@ -71,6 +75,11 @@ struct cdx_mcdi {
unsigned long mcdi_buf_use;
const struct cdx_mcdi_ops *mcdi_ops;
void *mcdi_buf;
+
+ struct rproc *r5_rproc;
+ struct rpmsg_device *rpdev;
+ struct rpmsg_endpoint *ept;
+ struct work_struct work;
};
struct cdx_mcdi_ops {
--
2.17.1
WARNING: multiple messages have this Message-ID (diff)
From: Nipun Gupta <nipun.gupta@amd.com>
To: <robh+dt@kernel.org>, <krzysztof.kozlowski+dt@linaro.org>,
<gregkh@linuxfoundation.org>, <rafael@kernel.org>,
<eric.auger@redhat.com>, <alex.williamson@redhat.com>,
<cohuck@redhat.com>, <song.bao.hua@hisilicon.com>,
<mchehab+huawei@kernel.org>, <maz@kernel.org>,
<f.fainelli@gmail.com>, <jeffrey.l.hugo@gmail.com>,
<saravanak@google.com>, <Michael.Srba@seznam.cz>,
<mani@kernel.org>, <yishaih@nvidia.com>, <jgg@ziepe.ca>,
<jgg@nvidia.com>, <robin.murphy@arm.com>, <will@kernel.org>,
<joro@8bytes.org>, <masahiroy@kernel.org>,
<ndesaulniers@google.com>, <linux-arm-kernel@lists.infradead.org>,
<linux-kbuild@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<devicetree@vger.kernel.org>
Cc: <okaya@kernel.org>, <harpreet.anand@amd.com>,
<nikhil.agarwal@amd.com>, <michal.simek@amd.com>, <git@amd.com>,
Abhijit Gangurde <abhijit.gangurde@amd.com>,
Nipun Gupta <nipun.gupta@amd.com>
Subject: [PATCH 06/19] bus/cdx: add rpmsg communication channel for CDX
Date: Tue, 17 Jan 2023 19:11:38 +0530 [thread overview]
Message-ID: <20230117134139.1298-7-nipun.gupta@amd.com> (raw)
In-Reply-To: <20230117134139.1298-1-nipun.gupta@amd.com>
From: Abhijit Gangurde <abhijit.gangurde@amd.com>
RPMsg is used as a transport communication channel. This
change introduces RPMsg driver and integrates it with the
CDX controller.
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
Signed-off-by: Nipun Gupta <nipun.gupta@amd.com>
---
drivers/bus/cdx/controller/Kconfig | 1 +
drivers/bus/cdx/controller/Makefile | 2 +-
drivers/bus/cdx/controller/cdx_controller.c | 36 +++-
drivers/bus/cdx/controller/cdx_controller.h | 30 +++
drivers/bus/cdx/controller/cdx_rpmsg.c | 222 ++++++++++++++++++++
drivers/bus/cdx/controller/mcdi.h | 9 +
6 files changed, 291 insertions(+), 9 deletions(-)
create mode 100644 drivers/bus/cdx/controller/cdx_controller.h
create mode 100644 drivers/bus/cdx/controller/cdx_rpmsg.c
diff --git a/drivers/bus/cdx/controller/Kconfig b/drivers/bus/cdx/controller/Kconfig
index 17f9c6be2fe1..aea3ac86d3aa 100644
--- a/drivers/bus/cdx/controller/Kconfig
+++ b/drivers/bus/cdx/controller/Kconfig
@@ -9,6 +9,7 @@ if CDX_BUS
config CDX_CONTROLLER
tristate "CDX bus controller"
+ select RPMSG
help
CDX controller drives the CDX bus. It interacts with
firmware to get the hardware devices and registers with
diff --git a/drivers/bus/cdx/controller/Makefile b/drivers/bus/cdx/controller/Makefile
index f7437c882cc9..f071be411d96 100644
--- a/drivers/bus/cdx/controller/Makefile
+++ b/drivers/bus/cdx/controller/Makefile
@@ -6,4 +6,4 @@
#
obj-$(CONFIG_CDX_CONTROLLER) += cdx-controller.o
-cdx-controller-objs := cdx_controller.o mcdi.o mcdi_functions.o
+cdx-controller-objs := cdx_controller.o cdx_rpmsg.o mcdi.o mcdi_functions.o
diff --git a/drivers/bus/cdx/controller/cdx_controller.c b/drivers/bus/cdx/controller/cdx_controller.c
index 9b910c9cb31e..b62a6d3b7bd4 100644
--- a/drivers/bus/cdx/controller/cdx_controller.c
+++ b/drivers/bus/cdx/controller/cdx_controller.c
@@ -8,6 +8,7 @@
#include <linux/of_platform.h>
#include <linux/cdx/cdx_bus.h>
+#include "cdx_controller.h"
#include "../cdx.h"
#include "mcdi_functions.h"
#include "mcdi.h"
@@ -53,20 +54,14 @@ static void cdx_mcdi_request(struct cdx_mcdi *cdx, u8 bufid,
const struct cdx_dword *hdr, size_t hdr_len,
const struct cdx_dword *sdu, size_t sdu_len)
{
- /*
- * This will get updated by rpmsg APIs, with RPMSG introduction
- * in CDX controller as a transport layer.
- */
+ cdx_rpmsg_send(cdx, hdr, hdr_len, sdu, sdu_len);
}
static void cdx_mcdi_read_response(struct cdx_mcdi *cdx_mcdi, u8 bufid,
struct cdx_dword *outbuf, size_t offset,
size_t outlen)
{
- /*
- * This will get updated by rpmsg APIs, with RPMSG introduction
- * in CDX controller as a transport layer.
- */
+ cdx_rpmsg_read_resp(cdx_mcdi, outbuf, offset, outlen);
}
static const struct cdx_mcdi_ops mcdi_ops = {
@@ -77,6 +72,19 @@ static const struct cdx_mcdi_ops mcdi_ops = {
.mcdi_put_buf = cdx_mcdi_put_buf,
};
+void cdx_rpmsg_post_probe(struct cdx_controller *cdx)
+{
+ /* Register CDX controller with CDX bus driver */
+ if (cdx_register_controller(cdx))
+ dev_err(cdx->dev, "Failed to register CDX controller\n");
+}
+
+void cdx_rpmsg_pre_remove(struct cdx_controller *cdx)
+{
+ cdx_unregister_controller(cdx);
+ cdx_mcdi_wait_for_quiescence(cdx->priv, MCDI_RPC_TIMEOUT);
+}
+
static int cdx_scan_devices(struct cdx_controller *cdx)
{
struct cdx_mcdi *cdx_mcdi = cdx->priv;
@@ -174,9 +182,19 @@ static int xlnx_cdx_probe(struct platform_device *pdev)
goto cdx_mcdi_buf_fail;
}
+ ret = cdx_setup_rpmsg(pdev);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to register CDX RPMsg transport\n");
+ goto cdx_rpmsg_fail;
+ }
+
dev_info(&pdev->dev, "Successfully registered CDX controller with RPMsg as transport\n");
return 0;
+cdx_rpmsg_fail:
+ kfree(cdx_mcdi->mcdi_buf);
+ cdx_mcdi->mcdi_buf = NULL;
cdx_mcdi_buf_fail:
kfree(cdx);
cdx_alloc_fail:
@@ -192,6 +210,8 @@ static int xlnx_cdx_remove(struct platform_device *pdev)
struct cdx_controller *cdx = platform_get_drvdata(pdev);
struct cdx_mcdi *cdx_mcdi = cdx->priv;
+ cdx_destroy_rpmsg(pdev);
+
kfree(cdx_mcdi->mcdi_buf);
kfree(cdx);
diff --git a/drivers/bus/cdx/controller/cdx_controller.h b/drivers/bus/cdx/controller/cdx_controller.h
new file mode 100644
index 000000000000..43b7c742df87
--- /dev/null
+++ b/drivers/bus/cdx/controller/cdx_controller.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Header file for the CDX Controller
+ *
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+ */
+
+#ifndef _CDX_CONTROLLER_H_
+#define _CDX_CONTROLLER_H_
+
+#include <linux/cdx/cdx_bus.h>
+#include "mcdi_functions.h"
+
+void cdx_rpmsg_post_probe(struct cdx_controller *cdx);
+
+void cdx_rpmsg_pre_remove(struct cdx_controller *cdx);
+
+int cdx_rpmsg_send(struct cdx_mcdi *cdx_mcdi,
+ const struct cdx_dword *hdr, size_t hdr_len,
+ const struct cdx_dword *sdu, size_t sdu_len);
+
+void cdx_rpmsg_read_resp(struct cdx_mcdi *cdx_mcdi,
+ struct cdx_dword *outbuf, size_t offset,
+ size_t outlen);
+
+int cdx_setup_rpmsg(struct platform_device *pdev);
+
+void cdx_destroy_rpmsg(struct platform_device *pdev);
+
+#endif /* _CDX_CONT_PRIV_H_ */
diff --git a/drivers/bus/cdx/controller/cdx_rpmsg.c b/drivers/bus/cdx/controller/cdx_rpmsg.c
new file mode 100644
index 000000000000..147c2fadf67f
--- /dev/null
+++ b/drivers/bus/cdx/controller/cdx_rpmsg.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Platform driver for CDX bus.
+ *
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
+ */
+
+#include <linux/rpmsg.h>
+#include <linux/remoteproc.h>
+#include <linux/of_platform.h>
+#include <linux/cdx/cdx_bus.h>
+#include <linux/module.h>
+
+#include "../cdx.h"
+#include "cdx_controller.h"
+#include "mcdi_functions.h"
+#include "mcdi.h"
+
+#define to_rproc_device(_dev) \
+ container_of(_dev, struct rproc, dev)
+
+static struct rpmsg_device_id cdx_rpmsg_id_table[] = {
+ { .name = "mcdi_ipc" },
+ { },
+};
+MODULE_DEVICE_TABLE(rpmsg, cdx_rpmsg_id_table);
+
+int cdx_rpmsg_send(struct cdx_mcdi *cdx_mcdi,
+ const struct cdx_dword *hdr, size_t hdr_len,
+ const struct cdx_dword *sdu, size_t sdu_len)
+{
+ char send_buf[MCDI_BUF_LEN] = {0};
+
+ memset(cdx_mcdi->mcdi_buf, 0x0, MCDI_BUF_LEN);
+
+ memcpy(send_buf, hdr, hdr_len);
+ memcpy(send_buf + hdr_len, sdu, sdu_len);
+
+ return rpmsg_send(cdx_mcdi->ept, send_buf, hdr_len + sdu_len);
+}
+
+void cdx_rpmsg_read_resp(struct cdx_mcdi *cdx_mcdi,
+ struct cdx_dword *outbuf, size_t offset,
+ size_t outlen)
+{
+ memcpy(outbuf, (void *)((u64)cdx_mcdi->mcdi_buf + offset), outlen);
+}
+
+static int find_remoteproc_child_dev(struct device *dev, void *data)
+{
+ return strstr(dev_name(dev), "remoteproc") ? 1 : 0;
+}
+
+static int cdx_attach_to_rproc(struct platform_device *pdev)
+{
+ struct platform_device *node_pdev;
+ struct device_node *r5_core_node;
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+ struct device *dev;
+ struct rproc *rp;
+ int ret;
+
+ dev = &pdev->dev;
+ cdx_c = platform_get_drvdata(pdev);
+ cdx_mcdi = cdx_c->priv;
+
+ r5_core_node = of_parse_phandle(dev->of_node, "xlnx,rproc", 0);
+ if (!r5_core_node) {
+ dev_err(&pdev->dev, "xlnx,rproc: invalid phandle\n");
+ return -EINVAL;
+ }
+
+ node_pdev = of_find_device_by_node(r5_core_node);
+ if (!node_pdev) {
+ ret = -EPROBE_DEFER;
+ goto pdev_err;
+ }
+
+ dev = device_find_child(&node_pdev->dev, NULL, find_remoteproc_child_dev);
+ if (!dev) {
+ dev_err(&pdev->dev, "no matching remoteproc device found\n");
+ ret = -ENODEV;
+ goto no_child_err;
+ }
+
+ rp = to_rproc_device(dev);
+
+ /* Attach to remote processor */
+ ret = rproc_boot(rp);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to attach to remote processor\n");
+ goto no_child_err;
+ }
+
+ cdx_mcdi->r5_rproc = rp;
+no_child_err:
+ put_device(&node_pdev->dev);
+pdev_err:
+ of_node_put(r5_core_node);
+ return ret;
+}
+
+static void cdx_detach_to_r5(struct platform_device *pdev)
+{
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+
+ cdx_c = platform_get_drvdata(pdev);
+ cdx_mcdi = cdx_c->priv;
+
+ rproc_detach(cdx_mcdi->r5_rproc);
+}
+
+static int cdx_rpmsg_cb(struct rpmsg_device *rpdev, void *data,
+ int len, void *priv, u32 src)
+{
+ struct cdx_controller *cdx_c = dev_get_drvdata(&rpdev->dev);
+ struct cdx_mcdi *cdx_mcdi = cdx_c->priv;
+
+ if (len > MCDI_BUF_LEN)
+ return -EINVAL;
+
+ memcpy(cdx_mcdi->mcdi_buf, data, len);
+ cdx_mcdi_process_cmd(cdx_mcdi, *(struct cdx_dword *)cdx_mcdi->mcdi_buf);
+
+ return 0;
+}
+
+static void cdx_rpmsg_post_probe_work(struct work_struct *work)
+{
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+
+ cdx_mcdi = container_of(work, struct cdx_mcdi, work);
+ cdx_c = dev_get_drvdata(&cdx_mcdi->rpdev->dev);
+ cdx_rpmsg_post_probe(cdx_c);
+}
+
+static int cdx_rpmsg_probe(struct rpmsg_device *rpdev)
+{
+ struct rpmsg_channel_info chinfo = {0};
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+
+ cdx_c = (struct cdx_controller *)cdx_rpmsg_id_table[0].driver_data;
+ cdx_mcdi = cdx_c->priv;
+
+ chinfo.src = RPMSG_ADDR_ANY;
+ chinfo.dst = rpdev->dst;
+ strscpy(chinfo.name, cdx_rpmsg_id_table[0].name,
+ strlen(cdx_rpmsg_id_table[0].name));
+
+ cdx_mcdi->ept = rpmsg_create_ept(rpdev, cdx_rpmsg_cb, NULL, chinfo);
+ if (!cdx_mcdi->ept) {
+ dev_err_probe(&rpdev->dev, -ENXIO,
+ "Failed to create ept for channel %s\n",
+ chinfo.name);
+ return -EINVAL;
+ }
+
+ cdx_mcdi->rpdev = rpdev;
+ dev_set_drvdata(&rpdev->dev, cdx_c);
+
+ schedule_work(&cdx_mcdi->work);
+ return 0;
+}
+
+static void cdx_rpmsg_remove(struct rpmsg_device *rpdev)
+{
+ struct cdx_controller *cdx_c = dev_get_drvdata(&rpdev->dev);
+ struct cdx_mcdi *cdx_mcdi = cdx_c->priv;
+
+ flush_work(&cdx_mcdi->work);
+ cdx_rpmsg_pre_remove(cdx_c);
+
+ rpmsg_destroy_ept(cdx_mcdi->ept);
+ dev_set_drvdata(&rpdev->dev, NULL);
+}
+
+static struct rpmsg_driver cdx_rpmsg_driver = {
+ .drv.name = KBUILD_MODNAME,
+ .id_table = cdx_rpmsg_id_table,
+ .probe = cdx_rpmsg_probe,
+ .remove = cdx_rpmsg_remove,
+ .callback = cdx_rpmsg_cb,
+};
+
+int cdx_setup_rpmsg(struct platform_device *pdev)
+{
+ struct cdx_controller *cdx_c;
+ struct cdx_mcdi *cdx_mcdi;
+ int ret;
+
+ /* Attach to remote processor */
+ ret = cdx_attach_to_rproc(pdev);
+ if (ret)
+ return ret;
+
+ cdx_c = platform_get_drvdata(pdev);
+ cdx_mcdi = cdx_c->priv;
+
+ /* Register RPMsg driver */
+ cdx_rpmsg_id_table[0].driver_data = (kernel_ulong_t)cdx_c;
+
+ INIT_WORK(&cdx_mcdi->work, cdx_rpmsg_post_probe_work);
+ ret = register_rpmsg_driver(&cdx_rpmsg_driver);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Failed to register cdx RPMsg driver: %d\n", ret);
+ cdx_detach_to_r5(pdev);
+ }
+
+ return ret;
+}
+
+void cdx_destroy_rpmsg(struct platform_device *pdev)
+{
+ unregister_rpmsg_driver(&cdx_rpmsg_driver);
+
+ cdx_detach_to_r5(pdev);
+}
diff --git a/drivers/bus/cdx/controller/mcdi.h b/drivers/bus/cdx/controller/mcdi.h
index a2ee8821b6fe..54e1b27c2a53 100644
--- a/drivers/bus/cdx/controller/mcdi.h
+++ b/drivers/bus/cdx/controller/mcdi.h
@@ -64,6 +64,10 @@ enum cdx_mcdi_cmd_state {
* @mcdi_buf_use: Stores MCDI buffer usage
* @mcdi_ops: MCDI operations
* @mcdi_buf: MCDI receive buffer
+ * @r5_rproc : R5 Remoteproc device handle
+ * @rpdev: RPMsg device
+ * @ept: RPMsg endpoint
+ * @work: Post probe work
*/
struct cdx_mcdi {
/* MCDI interface */
@@ -71,6 +75,11 @@ struct cdx_mcdi {
unsigned long mcdi_buf_use;
const struct cdx_mcdi_ops *mcdi_ops;
void *mcdi_buf;
+
+ struct rproc *r5_rproc;
+ struct rpmsg_device *rpdev;
+ struct rpmsg_endpoint *ept;
+ struct work_struct work;
};
struct cdx_mcdi_ops {
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2023-01-17 13:43 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-17 13:41 [PATCH 0/7] add support for CDX bus Nipun Gupta
2023-01-17 13:41 ` Nipun Gupta
2023-01-17 13:41 ` [PATCH 01/19] bus/cdx: add the cdx bus driver Nipun Gupta
2023-01-17 13:41 ` Nipun Gupta
2023-01-17 14:07 ` Greg KH
2023-01-17 14:07 ` Greg KH
2023-01-18 10:56 ` Gupta, Nipun
2023-01-18 10:56 ` Gupta, Nipun
2023-01-17 17:21 ` Randy Dunlap
2023-01-17 17:21 ` Randy Dunlap
2023-01-18 10:59 ` Gupta, Nipun
2023-01-18 10:59 ` Gupta, Nipun
2023-01-17 13:41 ` [PATCH 02/19] iommu/arm-smmu-v3: support ops registration for CDX bus Nipun Gupta
2023-01-17 13:41 ` Nipun Gupta
2023-01-17 13:41 ` [PATCH 03/19] dt-bindings: bus: add CDX bus controller device tree bindings Nipun Gupta
2023-01-17 13:41 ` Nipun Gupta
2023-01-17 17:54 ` Krzysztof Kozlowski
2023-01-17 17:54 ` Krzysztof Kozlowski
2023-01-18 12:39 ` Gupta, Nipun
2023-01-18 12:39 ` Gupta, Nipun
2023-01-18 12:43 ` Krzysztof Kozlowski
2023-01-18 12:43 ` Krzysztof Kozlowski
2023-01-19 7:33 ` Gupta, Nipun
2023-01-19 7:33 ` Gupta, Nipun
2023-01-17 13:41 ` [PATCH 04/19] bus/cdx: add MCDI protocol interface for firmware interaction Nipun Gupta
2023-01-17 13:41 ` Nipun Gupta
2023-01-17 14:08 ` Greg KH
2023-01-17 14:08 ` Greg KH
2023-01-18 10:58 ` Gupta, Nipun
2023-01-18 10:58 ` Gupta, Nipun
2023-01-17 13:41 ` [PATCH 05/19] bus/cdx: add cdx controller Nipun Gupta
2023-01-17 13:41 ` Nipun Gupta
2023-01-17 14:10 ` Greg KH
2023-01-17 14:10 ` Greg KH
2023-01-18 12:36 ` Gupta, Nipun
2023-01-18 12:36 ` Gupta, Nipun
2023-01-17 13:41 ` Nipun Gupta [this message]
2023-01-17 13:41 ` [PATCH 06/19] bus/cdx: add rpmsg communication channel for CDX Nipun Gupta
2023-01-17 13:41 ` [PATCH 07/19] bus/cdx: add device attributes Nipun Gupta
2023-01-17 13:41 ` Nipun Gupta
2023-01-17 14:13 ` Greg KH
2023-01-17 14:13 ` Greg KH
2023-01-18 13:03 ` Gupta, Nipun
2023-01-18 13:03 ` Gupta, Nipun
2023-01-17 17:47 ` [PATCH 0/7] add support for CDX bus Krzysztof Kozlowski
2023-01-17 17:47 ` Krzysztof Kozlowski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230117134139.1298-7-nipun.gupta@amd.com \
--to=nipun.gupta@amd.com \
--cc=Michael.Srba@seznam.cz \
--cc=abhijit.gangurde@amd.com \
--cc=alex.williamson@redhat.com \
--cc=cohuck@redhat.com \
--cc=devicetree@vger.kernel.org \
--cc=eric.auger@redhat.com \
--cc=f.fainelli@gmail.com \
--cc=git@amd.com \
--cc=gregkh@linuxfoundation.org \
--cc=harpreet.anand@amd.com \
--cc=jeffrey.l.hugo@gmail.com \
--cc=jgg@nvidia.com \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mani@kernel.org \
--cc=masahiroy@kernel.org \
--cc=maz@kernel.org \
--cc=mchehab+huawei@kernel.org \
--cc=michal.simek@amd.com \
--cc=ndesaulniers@google.com \
--cc=nikhil.agarwal@amd.com \
--cc=okaya@kernel.org \
--cc=rafael@kernel.org \
--cc=robh+dt@kernel.org \
--cc=robin.murphy@arm.com \
--cc=saravanak@google.com \
--cc=song.bao.hua@hisilicon.com \
--cc=will@kernel.org \
--cc=yishaih@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.