Vybrid Cortex-M4 Linux support – Status update

This is a status update about my work on Linux for Cortex-M4 inside Freescale Vybrid SoC’s. While I managed to boot Linux on the M4 core since fall last year, several improvements have been made since then.

MSCM interrupt router driver

Peripheral interrupts need to be routed to the core requiring them. The routing is done by the interrupt router inside MSCM (Miscellaneous System Control Module). So far, the boot loader (U-Boot) configured all interrupts to the primary core. A proper driver for the interrupt router was missing, hence to get Linux running on the secondary core, manual fiddling of the interrupt router registers was needed.

The IRQ domain hierarchy feature merged in 3.19 was an excellent fit to write a driver for the MSCM interrupt router within Vybrid: The hierarchy allows to model the interrupt controllers as stacked entities, which is exactly how the interrupt controllers are arranged in Vybrid. A interrupt needs to be routed to the CPU local interrupt controller through the MSCM interrupt router. Hence the standard device-trees for the Cortex-A5 CPU stack the MSCM-IR and GIC whereas the device-tree for the Cortex-M4 CPU stack the MSCM-IR and the NVIC interrupt controller.

The driver has been merged in the v4.1 merge window, however this version only works with the GIC (and hence the primary CPU). But patches to enable the driver in conjunction with NVIC will likely make it in the v4.2 merge window.

Cortex-M4 mini-loader

The mini-loader for the Cortex-M4 makes the hacked Linux kernel entry code (head-nommu.S) obsolete. It essentially copies the pointer to the device tree file from SRC_GPR3 (PERSISTENT_ARG1) to the M4 CPU’s r2 register. The mini loader is included within the m4boot utility for Linux and part of the U-Boot support for Cortex-M4 (see below).

Caches support

There are no standard cache controllers for the Cortex-M4, also caches are completely optional. The Vybrid SoC provides caches for the Cortex-M4 through the Local Memory Controller. Enabling caches especially boosts performance when running code from the relatively slow DDR memory. First I had some troubles after enabling caches, but it turned out that it works flawless when turning them on correctly. Latest versions of the vf610m4bootldr mini-loader enable both, data and instruction caches, which boosts performance from 4.30 to blazing 110.48 BogoMIPS, according to Linux 😀

Boot directly from U-Boot

A new U-Boot command m4boot allows to boot Linux on the Cortex-M4 directly from U-Boot. The first argument of the command is a pointer to a FIT image, which is currently the only image format which is supported. I opted for the FIT image since it allowed most flexibility. However, FIT image support is somewhat different from the standard FIT image support known from the bootm. Especially the entry points and load addresses which are required need to be carefully choosen when preparing the FIT image:

Kernel image:

Need to be a XIP (eXecute In-Place image)

The CONFIG_XIP_PHYS_ADDR defines the text base of the kernel and hence the target memory location of the image

Load Address is the target memory location from the Cortex-A5 viewpoint (e.g. 0x8f000080)

Entry Point is the same memory location from the Cortex-M4 viewpoint, plus 1 due to Thumb-2 jump address (e.g. 0x0f000081)

Initrd image (optional)

Load Address is the target memory location from the Cortex-A5 viewpoint where U-Boot copies the image to

Need to be in the memory area accessible by Linux (e.g. 0x8d000000)

Device Tree file

Load Address is the target memory location from the Cortex-A5 viewpoint where U-Boot copies the device tree to

Need to be in the memory area accessible by Linux (e.g. 0x8df00000)

A complete FIT image input file which works for the Linux vf610m4_defconfig standard configuration: