ipc_service: mi: Convert to device driver

As part of the work to support multiple IPC instances / backends using
IPC service, the static vrings mi code must be reworked to resemble a
classic device driver.

Fix also the sample using it.

Signed-off-by: Carlo Caione <ccaione@baylibre.com>
diff --git a/include/ipc/ipc_rpmsg.h b/include/ipc/ipc_rpmsg.h
index c3f742d..6778673 100644
--- a/include/ipc/ipc_rpmsg.h
+++ b/include/ipc/ipc_rpmsg.h
@@ -24,6 +24,8 @@
 /** Number of endpoints. */
 #define NUM_ENDPOINTS	CONFIG_IPC_SERVICE_NUM_ENDPOINTS_PER_INSTANCE
 
+struct ipc_rpmsg_ept;
+
 /**
  * @typedef rpmsg_ept_bound_cb
  * @brief Define the bound callback.
@@ -33,13 +35,13 @@
  *
  * @param ept Endpoint of the instance just bound.
  */
-typedef void (*rpmsg_ept_bound_cb)(struct ipc_ept *ept);
+typedef void (*rpmsg_ept_bound_cb)(struct ipc_rpmsg_ept *ept);
 
 /** @brief Endpoint structure.
  *
  *  Used to define an endpoint to be encapsulated in an RPMsg instance.
  */
-struct ipc_ept {
+struct ipc_rpmsg_ept {
 	/** RPMsg endpoint. */
 	struct rpmsg_endpoint ep;
 
@@ -62,7 +64,7 @@
  */
 struct ipc_rpmsg_instance {
 	/** Endpoints in the instance. */
-	struct ipc_ept endpoint[NUM_ENDPOINTS];
+	struct ipc_rpmsg_ept endpoint[NUM_ENDPOINTS];
 
 	/** RPMsg virtIO device. */
 	struct rpmsg_virtio_device rvdev;
@@ -115,7 +117,7 @@
  *  @retval Other errno codes depending on the OpenAMP implementation.
  */
 int ipc_rpmsg_register_ept(struct ipc_rpmsg_instance *instance, unsigned int role,
-			   struct ipc_ept *ept);
+			   struct ipc_rpmsg_ept *ept);
 
 /**
  * @}
diff --git a/samples/subsys/ipc/ipc_service/remote/src/main.c b/samples/subsys/ipc/ipc_service/remote/src/main.c
index cbf6b37..71d33a9 100644
--- a/samples/subsys/ipc/ipc_service/remote/src/main.c
+++ b/samples/subsys/ipc/ipc_service/remote/src/main.c
@@ -14,6 +14,8 @@
 
 #include <ipc/ipc_service.h>
 
+#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
+
 #define APP_TASK_STACK_SIZE  1024
 
 K_THREAD_STACK_DEFINE(thread_stack_1, APP_TASK_STACK_SIZE);
@@ -31,8 +33,8 @@
 static K_SEM_DEFINE(data_rx1_sem, 0, 1);
 static K_SEM_DEFINE(data_rx2_sem, 0, 1);
 
-static struct ipc_ept *ept_1;
-static struct ipc_ept *ept_2;
+static struct ipc_ept ept_1;
+static struct ipc_ept ept_2;
 
 static void ept_bound_1(void *priv)
 {
@@ -71,11 +73,15 @@
 	ARG_UNUSED(arg1);
 	ARG_UNUSED(arg2);
 	ARG_UNUSED(arg3);
+
+	const struct device *ipc_instance;
 	int status = 0;
 	uint8_t message = 0U;
 
 	printk("\r\nIPC Service [remote 1] demo started\r\n");
 
+	ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
+
 	static struct ipc_ept_cfg ept_cfg = {
 		.name = "ep_1",
 		.prio = 0,
@@ -87,7 +93,7 @@
 		},
 	};
 
-	status = ipc_service_register_endpoint(&ept_1, &ept_cfg);
+	status = ipc_service_register_endpoint(ipc_instance, &ept_1, &ept_cfg);
 	if (status < 0) {
 		printk("ipc_service_register_endpoint failed %d\n", status);
 		return;
@@ -101,7 +107,7 @@
 		printk("Remote [1] received a message: %d\n", message);
 
 		message++;
-		status = ipc_service_send(ept_1, &message, sizeof(message));
+		status = ipc_service_send(&ept_1, &message, sizeof(message));
 		if (status < 0) {
 			printk("send_message(%d) failed with status %d\n",
 			       message, status);
@@ -117,11 +123,15 @@
 	ARG_UNUSED(arg1);
 	ARG_UNUSED(arg2);
 	ARG_UNUSED(arg3);
+
+	const struct device *ipc_instance;
 	int status = 0;
 	uint8_t message = 0U;
 
 	printk("\r\nIPC Service [remote 2] demo started\r\n");
 
+	ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
+
 	static struct ipc_ept_cfg ept_cfg = {
 		.name = "ep_2",
 		.prio = 0,
@@ -133,7 +143,7 @@
 		},
 	};
 
-	status = ipc_service_register_endpoint(&ept_2, &ept_cfg);
+	status = ipc_service_register_endpoint(ipc_instance, &ept_2, &ept_cfg);
 
 	if (status < 0) {
 		printk("ipc_service_register_endpoint failed %d\n", status);
@@ -148,7 +158,7 @@
 		printk("Remote [2] received a message: %d\n", message);
 
 		message++;
-		status = ipc_service_send(ept_2, &message, sizeof(message));
+		status = ipc_service_send(&ept_2, &message, sizeof(message));
 		if (status < 0) {
 			printk("send_message(%d) failed with status %d\n",
 			       message, status);
diff --git a/samples/subsys/ipc/ipc_service/src/main.c b/samples/subsys/ipc/ipc_service/src/main.c
index 00bdb20..2bc1f50 100644
--- a/samples/subsys/ipc/ipc_service/src/main.c
+++ b/samples/subsys/ipc/ipc_service/src/main.c
@@ -15,6 +15,8 @@
 
 #include <ipc/ipc_service.h>
 
+#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
+
 #define APP_TASK_STACK_SIZE  1024
 
 K_THREAD_STACK_DEFINE(thread_stack_1, APP_TASK_STACK_SIZE);
@@ -32,8 +34,8 @@
 static K_SEM_DEFINE(data_rx1_sem, 0, 1);
 static K_SEM_DEFINE(data_rx2_sem, 0, 1);
 
-static struct ipc_ept *ept_1;
-static struct ipc_ept *ept_2;
+static struct ipc_ept ept_1;
+static struct ipc_ept ept_2;
 
 static void ept_bound_1(void *priv)
 {
@@ -72,11 +74,15 @@
 	ARG_UNUSED(arg1);
 	ARG_UNUSED(arg2);
 	ARG_UNUSED(arg3);
+
+	const struct device *ipc_instance;
 	int status = 0;
 	uint8_t message = 0U;
 
 	printk("\r\nIPC Service [master 1] demo started\r\n");
 
+	ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
+
 	static struct ipc_ept_cfg ept_cfg = {
 		.name = "ep_1",
 		.prio = 0,
@@ -88,7 +94,7 @@
 		},
 	};
 
-	status = ipc_service_register_endpoint(&ept_1, &ept_cfg);
+	status = ipc_service_register_endpoint(ipc_instance, &ept_1, &ept_cfg);
 	if (status < 0) {
 		printk("ipc_service_register_endpoint failed %d\n", status);
 		return;
@@ -97,7 +103,7 @@
 	k_sem_take(&bound_ept1_sem, K_FOREVER);
 
 	while (message < 100) {
-		status = ipc_service_send(ept_1, &message, sizeof(message));
+		status = ipc_service_send(&ept_1, &message, sizeof(message));
 		if (status < 0) {
 			printk("send_message(%d) failed with status %d\n",
 			       message, status);
@@ -119,11 +125,15 @@
 	ARG_UNUSED(arg1);
 	ARG_UNUSED(arg2);
 	ARG_UNUSED(arg3);
+
+	const struct device *ipc_instance;
 	int status = 0;
 	uint8_t message = 0U;
 
 	printk("\r\nIPC Service [master 2] demo started\r\n");
 
+	ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
+
 	static struct ipc_ept_cfg ept_cfg = {
 		.name = "ep_2",
 		.prio = 0,
@@ -135,7 +145,7 @@
 		},
 	};
 
-	status = ipc_service_register_endpoint(&ept_2, &ept_cfg);
+	status = ipc_service_register_endpoint(ipc_instance, &ept_2, &ept_cfg);
 
 	if (status < 0) {
 		printk("ipc_service_register_endpoint failed %d\n", status);
@@ -145,7 +155,7 @@
 	k_sem_take(&bound_ept2_sem, K_FOREVER);
 
 	while (message < 100) {
-		status = ipc_service_send(ept_2, &message, sizeof(message));
+		status = ipc_service_send(&ept_2, &message, sizeof(message));
 		if (status < 0) {
 			printk("send_message(%d) failed with status %d\n",
 			       message, status);
diff --git a/subsys/ipc/ipc_service/backends/ipc_rpmsg.c b/subsys/ipc/ipc_service/backends/ipc_rpmsg.c
index 5504b0d..5233192 100644
--- a/subsys/ipc/ipc_service/backends/ipc_rpmsg.c
+++ b/subsys/ipc/ipc_service/backends/ipc_rpmsg.c
@@ -16,7 +16,7 @@
 {
 	struct rpmsg_virtio_device *p_rvdev;
 	struct ipc_rpmsg_instance *instance;
-	struct ipc_ept *ept;
+	struct ipc_rpmsg_ept *ept;
 	int err;
 
 	p_rvdev = CONTAINER_OF(rdev, struct rpmsg_virtio_device, rdev);
@@ -41,7 +41,7 @@
 }
 
 int ipc_rpmsg_register_ept(struct ipc_rpmsg_instance *instance, unsigned int role,
-			   struct ipc_ept *ept)
+			   struct ipc_rpmsg_ept *ept)
 {
 	struct rpmsg_device *rdev;
 
diff --git a/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.c b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.c
index 9b20b4b..3762303 100644
--- a/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.c
+++ b/subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings_mi.c
@@ -17,6 +17,8 @@
 
 #include "ipc_rpmsg_static_vrings_mi.h"
 
+#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
+
 LOG_MODULE_REGISTER(ipc_rpmsg_multi_instance, CONFIG_IPC_SERVICE_LOG_LEVEL);
 
 #define WQ_STACK_SIZE	CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_WQ_STACK_SIZE
@@ -74,9 +76,14 @@
 
 static struct rpmsg_mi_instance instance[NUM_INSTANCES];
 
-static int send(struct ipc_ept *ept, const void *data, size_t len)
+static int send(const struct device *instance, void *token,
+		const void *data, size_t len)
 {
-	return rpmsg_send(&ept->ep, data, len);
+	struct ipc_rpmsg_ept *rpmsg_ept;
+
+	rpmsg_ept = (struct ipc_rpmsg_ept *) token;
+
+	return rpmsg_send(&rpmsg_ept->ep, data, len);
 }
 
 static struct rpmsg_mi_instance *get_available_instance(const struct ipc_ept_cfg *cfg)
@@ -90,7 +97,7 @@
 	return NULL;
 }
 
-static struct ipc_ept *get_available_ept_slot(struct ipc_rpmsg_instance *rpmsg_instance)
+static struct ipc_rpmsg_ept *get_available_ept_slot(struct ipc_rpmsg_instance *rpmsg_instance)
 {
 	for (size_t i = 0; i < NUM_ENDPOINTS; i++) {
 		if (rpmsg_instance->endpoint[i].name == NULL) {
@@ -168,7 +175,7 @@
 	instance->vr.shm_size = shm_local_size;
 }
 
-static void bound_cb(struct ipc_ept *ept)
+static void bound_cb(struct ipc_rpmsg_ept *ept)
 {
 	/* Notify the remote site that binding has occurred */
 	rpmsg_send(&ept->ep, (uint8_t *)"", 0);
@@ -180,9 +187,9 @@
 
 static int ept_cb(struct rpmsg_endpoint *ep, void *data, size_t len, uint32_t src, void *priv)
 {
-	struct ipc_ept *ept;
+	struct ipc_rpmsg_ept *ept;
 
-	ept = (struct ipc_ept *) priv;
+	ept = (struct ipc_rpmsg_ept *) priv;
 
 	if (len == 0) {
 		if (!ept->bound) {
@@ -239,14 +246,18 @@
 	return 0;
 }
 
-static int register_ept(struct ipc_ept **r_ept, const struct ipc_ept_cfg *cfg)
+static int register_ept(const struct device *dev,
+			void **token,
+			const struct ipc_ept_cfg *cfg)
 {
 	struct ipc_rpmsg_instance *rpmsg_instance;
 	struct rpmsg_mi_instance *instance;
-	struct ipc_ept *ept;
+	struct ipc_rpmsg_ept *rpmsg_ept;
 	int err;
 
-	if (!cfg || !r_ept) {
+	ARG_UNUSED(dev);
+
+	if (!cfg || !token) {
 		return -EINVAL;
 	}
 
@@ -283,29 +294,28 @@
 		instance->is_initialized = true;
 	}
 
-	ept = get_available_ept_slot(rpmsg_instance);
-	if (ept == NULL) {
+	rpmsg_ept = get_available_ept_slot(rpmsg_instance);
+	if (rpmsg_ept == NULL) {
 		return -ENODEV;
 	}
 
-	ept->name = cfg->name;
-	ept->cb = &cfg->cb;
-	ept->priv = cfg->priv;
-	ept->bound = false;
-	ept->ep.priv = ept;
+	rpmsg_ept->name = cfg->name;
+	rpmsg_ept->cb = &cfg->cb;
+	rpmsg_ept->priv = cfg->priv;
+	rpmsg_ept->bound = false;
+	rpmsg_ept->ep.priv = rpmsg_ept;
 
-	err = ipc_rpmsg_register_ept(rpmsg_instance, instance->role, ept);
+	err = ipc_rpmsg_register_ept(rpmsg_instance, instance->role, rpmsg_ept);
 	if (err != 0) {
 		return err;
 	}
 
-	*r_ept = ept;
+	(*token) = rpmsg_ept;
 
 	return 0;
 }
 
-const static struct ipc_service_backend backend = {
-	.name = "RPMSG backend - static VRINGs (multi-instance)",
+const static struct ipc_service_backend backend_ops = {
 	.send = send,
 	.register_endpoint = register_ept,
 };
@@ -321,6 +331,9 @@
 				   VIRTIO_DEV_MASTER : VIRTIO_DEV_SLAVE;
 	}
 
-	return ipc_service_register_backend(&backend);
+	return 0;
 }
-SYS_INIT(backend_init, POST_KERNEL, CONFIG_IPC_SERVICE_REG_BACKEND_PRIORITY);
+
+DEVICE_DEFINE(mi_backend, MI_BACKEND_DRIVER_NAME, &backend_init, NULL, NULL,
+	      NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+	      &backend_ops);