Linux PS SPI Slave Mode

This page describes how to use the PS SPI controller as a slave in Linux.

Table of Contents


Slave support for SPI was introduced into the Linux kernel in 2017 as described here: SPI Slave Support. A patch series,, has been pushed upstream recently supporting the PS SPI driver. The patch series is still not in a Xilinx release as of 2023.1 but it can easily be applied to the Xilinx kernel tree as described below. The following guidelines were tested with the 2023.1 release of PetaLinux using a ZCU102 board with two PS SPI controllers. One controller is set up as a SPI master and the second controller is set up to be a SPI slave. The loopback feature of the MIOs is used to connect the two controllers without any special hardware. The following guidelines assume the user has Linux and PetaLinux experience and is not intended to be tutorial for either.


ZCU102 Hardware

The MPSoC has three SPI controllers with the first being a QSPI controller at address 0xFF0F0000. By default, the QSPI controller is used in the PetaLinux BSP as shown below.

[ 3.053808] spi-nor spi0.0: found mt25qu512a, expected m25p80 [ 3.059755] spi-nor spi0.0: mt25qu512a (131072 Kbytes)

Because QSPI is a SPI controller, it is SPI bus 0 in Linux with the other two PS SPI controllers being buses 1 and 2 in the default ZCU102 BSP of PetaLinux. The PS SPI controllers are at addresses 0xFF040000 and 0xFF050000.

PetaLinux Project

The ZCU102 BSP for PetaLinux was used as the basis of the project. Create a PetaLinux project based on the BSP.

Kernel Configuration

The kernel configuration is altered to enable more SPI features including spidev (User mode SPI device driver) and the slave mode (SPI slave protocol handlers) along with the provided SPI slave handlers. Note that slave mode has been in the kernel for some time and patches are only required for the PS SPI controller to support the slave mode.


Power management with the PetaLinux BSP causes the SPI controllers to be non-functional as the PS SPI controllers are not used by default. Power management is turned off in the kernel.


Without power management, the following warnings are seen on the console, but the system is functional. The driver does not have any normal output when it successfully probes so that the interrupts can be seen in /proc/interrupts indicating the driver is working.

[ 20.065666] uio_pdrv_genirq: Unknown symbol pm_runtime_enable (err -2) [ 20.072221] uio_pdrv_genirq: Unknown symbol __pm_runtime_resume (err -2)

With power management on and when using the PetaLinux BSP, the following errors might be seen when the driver probes, and the system is not functional.

[ 3.070864] cdns-spi ff040000.spi: error -EACCES: failed to add to PM domain domain11 [ 3.078692] cdns-spi: probe of ff040000.spi failed with error -13 [ 3.090909] cdns-spi ff050000.spi: error -EACCES: failed to add to PM domain domain12 [ 3.098735] cdns-spi: probe of ff050000.spi failed with error -13

The alternative to turning off power management is to create a Vivado system and use EMIO for the two SPI controllers as illustrated below:



Patch Series

The patch series from AMD consists of two patches but there are other patches in Mark Brown's SPI integration kernel tree at For ease of integration, a ZIP file is attached to this page which also includes patches from the community. Testing is based on the use of all of the patches.

Applying Patches

An external kernel repository could be used and then PetaLinux configured to use that kernel with the patches. For this test, the patches are integrated into the PetaLinux project kernel recipe which is quicker.

Unzip the patch zip file into the kernel recipe area of the PetaLinux project at <project>/project-spec/meta-user/recipes-kernel/linux/linux-xlnx. Alter the Linux kernel recipe linux-xlnx_%.bbappend of the PetaLinux project to apply the patch series.

Device Tree Changes

The following device tree changes illustrate using the spidev driver with the first SPI Controller and making the second SPI Controller a slave. Note the compatible string for the spidev driver no longer works with “spidev” as it once did such that any compatible device from the spidev driver, such as “lwn,bk4”, can be used in the device tree.

Optionally, the SPI slave protocol handler can be set in the device tree, and then it seems that it cannot be dynamically changed at run-time. Most of the testing illustrated on this page did not set it in the device tree. The following example illustrates setting the handler to be the “spi-slave-time” handler.

Test Application

The spidev_test.c application provided in the Linux kernel tree at is used for testing. An application is created in PetaLinux to build the application.

The source code file, spidev_test.c, is taken from the kernel tree, renamed to spidev-test.c, and placed into the PetaLinux application recipe at <project>/project-spec/meta-user/recipe-apps/spidev-test/files/spidev-test.c.

PetaLinux does not allow the use of the “_” character.


MIO SPI Loopback

The IOU System Controller block of MPSoC allows MIO devices to be looped back between 2 of the same controllers and in this test the SPI controllers are connected together. A write to the IOU SLCR is accomplished from user space using devmem before the tests are performed.

After Boot

You should see the following when the system is correct. SPI bus 1 is the master controller using the spidev driver.

Slave Time Protocol Test

Spidev Protocol Test

The spidev driver can also be used for the slave protocol. As with the device tree, “spidev” is not used for the name of the driver but a compatible device in the driver, such as “bk4”.

Resolved Issues

A kernel driver issue was happening sometimes, about 30% of the time, as illustrated below. This issue was resolved with a patch that is the last in the patch series attached to the page above.


© Copyright 2019 - 2022 Xilinx Inc. Privacy Policy