Converting Ethos-U driver to rpmsg

The Ethos-U kernel driver has been converted from a
platform driver with a custom firmware interface into a
rpmsg driver.

Change-Id: I9ae449f5e79eb02924e6630611d0893e5fec86be
diff --git a/kernel/ethosu_driver.c b/kernel/ethosu_driver.c
index a530f95..c6fc8cd 100644
--- a/kernel/ethosu_driver.c
+++ b/kernel/ethosu_driver.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2022 Arm Limited.
+ * Copyright 2020-2023 Arm Limited and/or its affiliates
  *
  * This program is free software and is provided to you under the terms of the
  * GNU General Public License version 2 as published by the Free Software
@@ -24,7 +24,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/platform_device.h>
+#include <linux/rpmsg.h>
 
 #include "ethosu_device.h"
 
@@ -38,6 +38,8 @@
 #define MINOR_BASE      0 /* Minor version starts at 0 */
 #define MINOR_COUNT    64 /* Allocate minor versions */
 
+#define DMA_ADDR_BITS 32  /* Number of address bits */
+
 /****************************************************************************
  * Variables
  ****************************************************************************/
@@ -49,105 +51,98 @@
 static DECLARE_BITMAP(minors, MINOR_COUNT);
 
 /****************************************************************************
- * Arm Ethos-U
+ * Rpmsg driver
  ****************************************************************************/
 
-static int ethosu_pdev_probe(struct platform_device *pdev)
+static int ethosu_rpmsg_probe(struct rpmsg_device *rpdev)
 {
+	struct device *dev = &rpdev->dev;
 	struct ethosu_device *edev;
-	struct resource *in_queue_res;
-	struct resource *out_queue_res;
 	int minor;
 	int ret;
 
-	dev_info(&pdev->dev, "Probe\n");
-
+	/* Reserve minor number for device node */
 	minor = find_first_zero_bit(minors, MINOR_COUNT);
 	if (minor >= MINOR_COUNT) {
-		dev_err(&pdev->dev, "No more minor numbers.\n");
+		dev_err(dev, "No more minor numbers.");
 
 		return -ENOMEM;
 	}
 
-	/* Get path to TCM memory */
-	in_queue_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						    "in_queue");
-	if (IS_ERR(in_queue_res)) {
-		dev_err(&pdev->dev, "Failed to get in_queue resource.\n");
-
-		return PTR_ERR(in_queue_res);
-	}
-
-	out_queue_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						     "out_queue");
-	if (IS_ERR(out_queue_res)) {
-		dev_err(&pdev->dev, "Failed to get out_queue resource.\n");
-
-		return PTR_ERR(out_queue_res);
-	}
-
-	/* Allocate memory for Arm Ethos-U device */
-	edev = devm_kzalloc(&pdev->dev, sizeof(*edev), GFP_KERNEL);
+	edev = devm_kzalloc(dev, sizeof(*edev), GFP_KERNEL);
 	if (!edev)
 		return -ENOMEM;
 
-	platform_set_drvdata(pdev, edev);
+	dev_set_drvdata(dev, edev);
 
 	/* Initialize device */
-	ret = ethosu_dev_init(edev, &pdev->dev, ethosu_class,
-			      MKDEV(MAJOR(devt), minor), in_queue_res,
-			      out_queue_res);
+	ret = ethosu_dev_init(edev, rpdev, ethosu_class,
+			      MKDEV(MAJOR(devt), minor));
 	if (ret)
-		goto free_dev;
+		return ret;
 
 	set_bit(minor, minors);
 
 	return 0;
-
-free_dev:
-	devm_kfree(&pdev->dev, edev);
-
-	return ret;
 }
 
-static int ethosu_pdev_remove(struct platform_device *pdev)
+static void ethosu_rpmsg_remove(struct rpmsg_device *rpdev)
 {
-	struct ethosu_device *edev = platform_get_drvdata(pdev);
+	struct ethosu_device *edev = dev_get_drvdata(&rpdev->dev);
+
+	dev_info(&rpdev->dev, "%s", __FUNCTION__);
 
 	clear_bit(MINOR(edev->devt), minors);
 	ethosu_dev_deinit(edev);
-
-	return 0;
 }
 
-static const struct of_device_id ethosu_pdev_match[] = {
-	{ .compatible = "arm,ethosu" },
-	{ /* Sentinel */ },
+static int ethosu_rpmsg_cb(struct rpmsg_device *rpdev,
+			   void *data,
+			   int len,
+			   void *priv,
+			   u32 src)
+{
+	dev_err(&rpdev->dev, "%s", __FUNCTION__);
+
+	return -EINVAL;
+}
+
+static struct rpmsg_device_id ethosu_rpmsg_driver_id_table[] = {
+	{ .name = "ethos-u-0.0" },
+	{},
 };
 
-MODULE_DEVICE_TABLE(of, ethosu_pdev_match);
+MODULE_DEVICE_TABLE(rpmsg, ethosu_rpmsg_driver_id_table);
 
-static struct platform_driver ethosu_pdev_driver = {
-	.probe                  = &ethosu_pdev_probe,
-	.remove                 = &ethosu_pdev_remove,
-	.driver                 = {
-		.name           = ETHOSU_DRIVER_NAME,
-		.owner          = THIS_MODULE,
-		.of_match_table = of_match_ptr(ethosu_pdev_match),
+static struct rpmsg_driver ethosu_rpmsg_driver = {
+	.drv           = {
+		.name  = ETHOSU_DRIVER_NAME,
+		.owner = THIS_MODULE,
 	},
+	.id_table      = ethosu_rpmsg_driver_id_table,
+	.probe         = ethosu_rpmsg_probe,
+	.callback      = ethosu_rpmsg_cb,
+	.remove        = ethosu_rpmsg_remove,
 };
 
 /****************************************************************************
  * Module init and exit
  ****************************************************************************/
 
+static void __exit ethosu_exit(void)
+{
+	unregister_rpmsg_driver(&ethosu_rpmsg_driver);
+	unregister_chrdev_region(devt, MINOR_COUNT);
+	class_destroy(ethosu_class);
+}
+
 static int __init ethosu_init(void)
 {
 	int ret;
 
 	ethosu_class = class_create(THIS_MODULE, ETHOSU_DRIVER_NAME);
 	if (IS_ERR(ethosu_class)) {
-		printk("Failed to create class '%s'.\n", ETHOSU_DRIVER_NAME);
+		pr_err("Failed to create class '%s'.\n", ETHOSU_DRIVER_NAME);
 
 		return PTR_ERR(ethosu_class);
 	}
@@ -155,13 +150,13 @@
 	ret = alloc_chrdev_region(&devt, MINOR_BASE, MINOR_COUNT,
 				  ETHOSU_DRIVER_NAME);
 	if (ret) {
-		printk("Failed to allocate chrdev region.\n");
+		pr_err("Failed to allocate chrdev region.\n");
 		goto destroy_class;
 	}
 
-	ret = platform_driver_register(&ethosu_pdev_driver);
+	ret = register_rpmsg_driver(&ethosu_rpmsg_driver);
 	if (ret) {
-		printk("Failed to register Arm Ethos-U platform driver.\n");
+		pr_err("Failed to register Arm Ethos-U rpmsg driver.\n");
 		goto region_unregister;
 	}
 
@@ -176,15 +171,9 @@
 	return ret;
 }
 
-static void __exit ethosu_exit(void)
-{
-	platform_driver_unregister(&ethosu_pdev_driver);
-	unregister_chrdev_region(devt, MINOR_COUNT);
-	class_destroy(ethosu_class);
-}
-
 module_init(ethosu_init)
 module_exit(ethosu_exit)
+
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Arm Ltd");
 MODULE_DESCRIPTION("Arm Ethos-U NPU Driver");