[LINUX] Remote Processor Framework (1/3)

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation/remoteproc.txt

Remote Processor Framework

Introduction

Modern SoCs typically have heterogeneous remote processor devices in asymmetric multiprocessing (AMP) configurations, which may be running different instances of operating system, whether it's Linux or any other flavor of real-time OS.

A general SoC in recent years has a heterogeneous remote processor device as an asymmetric multi processing (AMP). It can run instances of different operating systems such as Linux or other real-time operating systems.

OMAP4, for example, has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP. In a typical configuration, the dual cortex-A9 is running Linux in a SMP configuration, and each of the other three cores (two M3 cores and a DSP) is running its own instance of RTOS in an AMP configuration.

For example, OMAP4 has a C64x + DSP as dual Cortex-A9, dia; Cortex-M3. In a typical configuration, dual cortex-A9 runs Linux in an SMP configuration, and the remaining three cores (two M3 cores and DSP) run their respective RTOS instances in an AMP configuration.

The remoteproc framework allows different platforms/architectures to control (power on, load firmware, power off) those remote processors while abstracting the hardware differences, so the entire driver doesn't need to be duplicated. In addition, this framework also adds rpmsg virtio devices for remote processors that supports this kind of communication. This way, platform-specific remoteproc drivers only need to provide a few low-level handlers, and then all rpmsg drivers will then just work (for more information about the virtio-based rpmsg bus and its drivers, please read Documentation/rpmsg.txt).

The remoteproc framework abstracts the differences in hardware and provides control (power on, firmware load, power off) for different platforms / architectures for the remote processor. There is no need to duplicate the entire driver. In addition, this framework also adds an rpmsg virtio device with a remote processor that supports this type of communication. Thus, the platform-specific remoteproc driver only needs to provide a few low-level handlers, after which all rpmsg drivers will work properly (virtio-based rpmsg bus and its driver updates). See Document / rpmsg.txt for information that

Registration of other types of virtio devices is now also possible. Firmwares just need to publish what kind of virtio devices do they support, and then remoteproc will add those devices. This makes it possible to reuse the existing virtio drivers with remote processor backends at a minimal development cost.

It is also possible to register other types of virtio devices. Firmware only exposes the types of virtio devices they support, and remoteproc adds those devices. This allows the remote processor backend to reuse an existing virtio driver with minimal development costs.

User API

int rproc_boot(struct rproc *rproc)

Boot a remote processor (i.e. load its firmware, power it on, ...).

Starting the remote processor (eg firmware load, power on)

If the remote processor is already powered on, this function immediately returns (successfully).

If the remote processor is already powered on, this function will return immediately (as a success).

Returns 0 on success, and an appropriate error value otherwise.

If successful, the return value is 0, otherwise an appropriate error value is entered.

Note: to use this function you should already have a valid rproc handle. There are several ways to achieve that cleanly (devres, pdata, the way remoteproc_rpmsg.c does this, or, if this becomes prevalent, we might also consider using dev_archdata for this).

Note: If you want to use this function, you need to prepare a valid rpoc handle in advance. There are several ways to achieve that cleanly. (devres, pdata, how to use this remoteproc_rpmsg.c, you can also consider using dev_archdata if it becomes popular)

void rproc_shutdown(struct rproc *rproc)

Power off a remote processor (previously booted with rproc_boot()). In case @rproc is still being used by an additional user(s), then this function will just decrement the power refcount and exit, without really powering off the device.

Power off remote processor (previously booted with rpoc_boot ()) If prpoc was already used by another user, this function will exit with a reduced power refcount and the actual device power off Not performed.

Every call to rproc_boot() must (eventually) be accompanied by a call to rproc_shutdown(). Calling rproc_shutdown() redundantly is a bug.

Every call to rpoc_boot () should (eventually) be accompanied by a call to rpoc_shutdown (). Unnecessary calls to rpoc_shutdown () are a bug.

note

we're not decrementing the rproc's refcount, only the power refcount. which means that the @rproc handle stays valid even after rproc_shutdown() returns, and users can still use it with a subsequent rproc_boot(), if needed.

Instead of reducing the rproc refcount, only reduce the power refcount. That is, the rpoc handle is still valid when you return from rpoc_shutdown () and can be used by the user in subsequent rppc_boot () if needed.

struct rproc *rproc_get_by_phandle(phandle phandle)

Find an rproc handle using a device tree phandle. Returns the rproc handle on success, and NULL on failure. This function increments the remote processor's refcount, so always use rproc_put() to decrement it back once rproc isn't needed anymore.

Use the device tree phandle to search for the rpoc handle. Returns rpoc handle on success, NULL on failure. This function increments the remote processor's refund. If you no longer need rpoc, use rpoc_put () to reduce it.

Typical usage

  #include <linux/remoteproc.h>

  /* in case we were given a valid 'rproc' handle */
  /*Valid`rpoc`In the case where handle is obtained*/
  int dummy_rproc_example(struct rproc *my_rproc)
  {
	int ret;

	/* let's power on and boot our remote processor */
    /*Power on and start remote processor*/
	ret = rproc_boot(my_rproc);
	if (ret) {
		/*
		 * something went wrong. handle it and leave.
		 */
        /*
         *Something went wrong, please handle it and leave
         */
	}

	/*
	 * our remote processor is now powered on... give it some work
	 */

    /*
     *The remote processor is now powered on, give it a job.
     */

	/* let's shut it down now */
    /*Power off*/
	rproc_shutdown(my_rproc);
  }

Originally, it is a part of the Linux Kernel source code, so it will be treated as GPLv2 (recognition that it should be).

https://www.kernel.org/doc/html/latest/index.html

Licensing documentation

The following describes the license of the Linux kernel source code (GPLv2), how to properly mark the license of individual files in the source tree, as well as links to the full license text.

https://www.kernel.org/doc/html/latest/process/license-rules.html#kernel-licensing

Recommended Posts

Remote Processor Framework (3/3)
Remote Processor Framework (1/3)
Remote Processor Framework (2/3)