Short Problem Description:
I'm experiencing SPI speed limitations on RK3506B. When trying to achieve the documented 50 MHz SPI speed, the actual measured throughput only reaches about 30 Mbps maximum.
What I've tried:
Configured SPI0 in DTS with assigned-clock-rates = <100000000> and spi-max-frequency = <50000000>
Tested using Python scripts that measure buffer transfer times
Real-world measurements show ~30 Mbps maximum, regardless of requested speed settings
Current DTS configuration:
dts
&spi0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi0m0_pins>;
rockchip,rx-sample-delay-ns = <10>;
rockchip,cs-setup-ns = <10>;
rockchip,cs-hold-ns = <10>;
clock-frequency = <100000000>;
clocks = <&cru CLK_SPI0>;
clock-names = "spiclk";
assigned-clocks = <&cru CLK_SPI0>;
assigned-clock-rates = <100000000>;
spidev@0 {
compatible = "rockchip,spidev";
spi-max-frequency = <50000000>;
reg = <0>;
};
};
The issue:
Despite proper DTS configuration and requesting 50 MHz, the actual SPI clock measured on the CLK pin shows only about 30 MHz maximum. The BAUDR register appears to be stuck at divider 4, giving ~23.44 MHz from the 187.5 MHz parent clock, but real throughput is even lower.
Questions:
Is there a known hardware limitation in RK3506 that prevents reaching 50 MHz SPI?
Are there specific clock configurations or pinctrl settings required for high-speed SPI?
Has anyone successfully achieved 50 MHz SPI on RK3506?
Should I try SPI1 instead of SPI0?
Additional info: Testing was done with Python's spidev interface, measuring actual transfer times of data buffers to calculate real throughput.
Luckfox Lyra Ultra W Trying to achieve 50Mhz on SPI0
Hello, for the spi0 device tree, do not set "assigned-clock-rates = <100000000>;". By default, it is already using 187500000 Hz. The measured rate can be set to 50M, 33.33M, 25M, 20M (no lower rates have been tested yet). Setting it to 100 MHz may cause the final division to stop at below 50M. Selecting to use 33.33M is recommended instead.
The test program I used is as follows. After cross-compilation and running, a 50 MHz clock signal can be collected on the SCL board.
The test program I used is as follows. After cross-compilation and running, a 50 MHz clock signal can be collected on the SCL board.
Code: Select all
>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
#include <string.h>
#define SPI_DEVICE_PATH "/dev/spidev0.0"
int main() {
int spi_file,ret;
uint8_t tx_buffer[50];
uint8_t rx_buffer[50];
/* Open the SPI device */
if ((spi_file = open(SPI_DEVICE_PATH, O_RDWR)) < 0) {
perror("Failed to open SPI device");
return -1;
}
/* Configure SPI mode and bits per word */
uint8_t mode = SPI_MODE_0 ;
uint8_t bits = 8;
if (ioctl(spi_file, SPI_IOC_WR_MODE, &mode) < 0) {
perror("Failed to set SPI mode");
close(spi_file);
return -1;
}
if (ioctl(spi_file, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) {
perror("Failed to set SPI bits per word");
close(spi_file);
return -1;
}
/* Perform SPI transfer */
struct spi_ioc_transfer transfer = {
.tx_buf = (unsigned long)tx_buffer,
.rx_buf = (unsigned long)rx_buffer,
.len = sizeof(tx_buffer),
.delay_usecs = 0,
.speed_hz = 50000000, // SPI speed in Hz
.bits_per_word = 8,
};
/* Send Data */
for (int i = 0; i < transfer.len; i++)
tx_buffer[i] = i;
ret = ioctl(spi_file, SPI_IOC_MESSAGE(1), &transfer);
if ( ret < 0) {
perror("Failed to perform SPI transfer");
close(spi_file);
return -1;
}
printf("Send %d bytes of data max speed: %d Hz.\n",transfer.len,transfer.speed_hz);
/* Print rx_buffer*/
printf("---------Receive %d bytes of data max speed:%d Hz---------\n",transfer.len, transfer.speed_hz);
printf("SPI RX: 0x%08X:", 0);
for (int i = 0; i < ret; i++) {
printf(" %02X",rx_buffer[i] );
if ((i + 1) % 16 == 0){
printf("\nSPI RX: 0x%08X:", i+1);
}
}
printf("\n");
/* Close the SPI device */
close(spi_file);
return 0;
}

