Enabling SPI on the RK3588: From Kernel Tweaks to User-Space Tests
Hardware Overviwe
The RK3588 exposes four native SPI controllers. Each controller can be clocked up to 50 MHz in master mode and supports 8-bit or 16-bit word lengths. The pin mapping is fixed:
- SPI0_MOSI – GPIO4_B0
- SPI0_MISO – GPIO4_B1
- SPI0_CLK – GPIO4_B2
- SPI0_CS0 – GPIO4_B3
These pins are 3.3 V tolerant and can source 8 mA, which is sufficient for short PCB traces or FFC cables up to 15 cm.
Device-Tree Changes
Add the following node to rk3588.dtsi or an overlay file:
&spi0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
spidev@0 {
compatible = "rockchip,spidev";
reg = <0>;
spi-max-frequency = <50000000>;
};
};
Re-compile the DTB and flash it to the board. After reboot, /dev/spidev0.0 should appear.
Kernel Configuration
Enable the following symbols in .config or via menuconfig:
CONFIG_SPI_ROCKCHIP=y
CONFIG_SPI_SPIDEV=y
CONFIG_SPI_MASTER=y
Rebuild the kernel and modules, then install them on the target.
User-Space Test Utility
A minimal C program to exchange one byte with a slave device:
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
int main(void)
{
int fd = open("/dev/spidev0.0", O_RDWR);
if (fd < 0) return 1;
uint8_t mode = SPI_MODE_0;
uint8_t bits = 8;
uint32_t speed = 1000000;
ioctl(fd, SPI_IOC_WR_MODE, &mode);
ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
uint8_t tx = 0xAA, rx = 0;
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)&tx,
.rx_buf = (unsigned long)&rx,
.len = 1,
.speed_hz = speed,
.bits_per_word = bits,
};
ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
close(fd);
return 0;
}
Compile with arm-linux-gnueabihf-gcc spi_test.c -o spi_test and run on the RK3588.
Verifying the Bus
Connect a logic analyser to CLK and MOSI. You should observe an 8-bit burst at 1 MHz with the pattern 10101010. If the slave responds, the same byte will appear on MISO.
Common Pitfalls
- Pin conflict: Ensure no other peripheral (e.g., eMMC) claims the same pins.
- Clock stretching: Some slaves require pauses between bytes; lower the speed to 500 kHz for initial tests.
- CS timing: If the slave expects CS to stay low across multiple words, set
SPI_CS_HIGHor use manual GPIO control.