Description
The SPI transfer speed used on RPi4 is 2 times slower (50kHz) than requested for example here: https://github.com/raspberrypi/linux/blob/rpi-4.19.y/sound/soc/bcm/pisound.c#L329 (100kHz)
On RPi4, requesting 100000 Hz produces 50kHz communcation speed. Changing the requested speed to 200000 Hz, on RPi4 it first starts at 80kHz, then at some point it switches to 100kHz, so that means RPi4 is capable of using exactly 100kHz.
On RPi3B+, requesting 100000 yields 62.5kHz speed. Requesting 200000 gives 125kHz. I assume RPi3B+ does not have in-between speeds like RPi4.
The question (and bug) is - why does RPi4 pick 50kHz when requested 100kHz instead, even though it can be seen being capable of 80kHz and 100kHz speeds.
To reproduce
Without any hat connected, you may run spidev_test to test drive /dev/spidev.0.0. Either an oscilloscope or logic analyzer can be connected to SCK line to measure the frequency, or it can very roughly be inferred based on the reported data rate and the duration of execution. Here are test results of sending 80000 bytes in 16 byte transfers using 100kHz and 200kHz requested speeds on RPi4 and 3B+, they contain SPI logic analyzer timed output, as well as the spidev_test invocation, results and additional notes at the very bottom.
100kHz RPi4
pi@raspberrypi:~/spidev_test $ time { ./spidev_test -S 16 -I 5000 -D /dev/spidev0.0 -s 100000; }
spi mode: 0x0
bits per word: 8
max speed: 100000 Hz (100 KHz)
rate: tx 41.1kbps, rx 41.1kbps
rate: tx 41.8kbps, rx 41.8kbps
rate: tx 41.8kbps, rx 41.8kbps
total: tx 78.1KB, rx 78.1KB
real 0m18.392s
user 0m0.056s
sys 0m0.286s
Actual transfer rate: 4351.44 B/s
Theoretical 50kHz rate: 6250 B/s
Theoretical 100kHz rate: 12500 B/s
Logic analyzer measured SCK rate: 40kHz
100kHz RPi3B+
pi@raspberrypi:~/spidev_test $ time { ./spidev_test -S 16 -I 5000 -D /dev/spidev0.0 -s 100000; }
spi mode: 0x0
bits per word: 8
max speed: 100000 Hz (100 KHz)
rate: tx 54.4kbps, rx 54.4kbps
rate: tx 64.8kbps, rx 64.8kbps
total: tx 78.1KB, rx 78.1KB
real 0m11.838s
user 0m0.050s
sys 0m0.214s
Actual transfer rate: 6763.58 B/s
Theoretical 50kHz rate: 6250 B/s
Theoretical 100kHz rate: 12500 B/s
Logic analyzer measured SCK rate: 62.5kHz
200kHz RPi4
pi@raspberrypi:~/spidev_test $ time { ./spidev_test -S 16 -I 5000 -D /dev/spidev0.0 -s 200000; }
spi mode: 0x0
bits per word: 8
max speed: 200000 Hz (200 KHz)
rate: tx 69.1kbps, rx 69.1kbps
total: tx 78.1KB, rx 78.1KB
real 0m9.369s
user 0m0.040s
sys 0m0.312s
Actual transfer rate: 8544.44 B/s
Theoretical 50kHz rate: 6250 B/s
Theoretical 100kHz rate: 12500 B/s
Logic analyzer measured SCK rate: 80kHz
200kHz RPi3B+
pi@raspberrypi:~/spidev_test $ time { ./spidev_test -S 16 -I 5000 -D /dev/spidev0.0 -s 200000; }
spi mode: 0x0
bits per word: 8
max speed: 200000 Hz (200 KHz)
rate: tx 125.1kbps, rx 125.1kbps
total: tx 78.1KB, rx 78.1KB
real 0m6.120s
user 0m0.045s
sys 0m0.232s
Actual transfer rate: 13086.32 B/s
Theoretical 50kHz rate: 6250 B/s
Theoretical 100kHz rate: 12500 B/s
Logic analyzer measured SCK rate: 125kHz
As can be seen from the results of same command being executed on RPi3B+ and RPi4, the tests finish significantly faster on RPi3B+.
Expected behaviour
100kHz gets picked when requesting 100kHz speed, or at least something closer like 80kHz.
System
RPi 3B+ and RPi 4 using latest Raspbian Lite running:
Linux raspberrypi 4.19.88-v7+ #1284 SMP Wed Dec 11 13:46:41 GMT 2019 armv7l GNU/Linux