In a project I’m working on I need to communicate with a BrickPi3 using a Raspberry Pi 3 Model B. For this reason I need to enable SPI. If I were using Raspbian it would mean just adding dtparam=spi=on to /boot/config.txt, but this file is not part of the NixOS boot process. I also want to just flash an SD-card and plug it into the Pi without having to run some actual installation:
{ pkgs, lib, ... }: {
imports = [
<nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix>
];
# We can only flash an uncompressed image.
# Additionally, compression whilst emulating the platform takes a looong time.
sdImage.compressImage = false;
# Latest release of major 5 doesn't always play ball with the hardware.
# Relase 4.19 is stable and "battle-tested".
# See <https://github.com/NixOS/nixpkgs/issues/82455>.
boot.kernelPackages = pkgs.linuxPackages_4_19;
# Other system configurations (services, software environments)
# omitted for brevity
}
A nixos-generate of the above derivation gives me an image that boots without problems.
Now, according to the NixOS wiki on the Raspberry, to enable audio one needs to add boot.loader.raspberryPi.firmwareConfig = ''dtparam=audio=on'' to the configuration, but mirroring this with dtparam=spi=on instead has no effect. Does anyone know how it should be done? In the end I expect some SPI driver to be listed by lsmod.
sd-image-aarch64.nix has a section that looks similar to what is usually written into a /boot/config.txt:
sdImage = {
populateFirmwareCommands = let
configTxt = pkgs.writeText "config.txt" ''
kernel=u-boot-rpi3.bin
# Boot in 64-bit mode.
arm_control=0x200
# U-Boot used to need this to work, regardless of whether UART is actually used or not.
# TODO: check when/if this can be removed.
enable_uart=1
# Prevent the firmware from smashing the framebuffer setup done by the mainline kernel
# when attempting to show low-voltage or overtemperature warnings.
avoid_warnings=1
'';
in ''
(cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/firmware/)
cp ${pkgs.ubootRaspberryPi3_64bit}/u-boot.bin firmware/u-boot-rpi3.bin
cp ${configTxt} firmware/config.txt
'';
populateRootCommands = ''
mkdir -p ./files/boot
${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/boot
'';
};
but appending dtparam=spi=on to the generated config.txt seems to have no effect.
sorry for resurrecting a three year old thread here but I just can’t seem to get this working on my Raspberry Pi 3 Model B even applying your overlay @Tmplt - perhaps something changed in the last three years? I know it’s a shot in the dark but if you still have this working I’d take any pointers. I’ve tried a few things but alas! it says it applies during a rebuild but I don’t see /dev/spi
yep, I used the bits from there to get the rebuild to work and it says it applies but no dice after a reboot. Anyway, I’m sure I’ll figure it out or just give up at some point. Thanks so much for the reply three years down the road!
Working for years for me with mainline Linux, currently Linux ttn-gw 5.10.93. Think I’ve built it last year, using boot.kernelPackages = pkgs.linuxPackages; (NixOS 22.05).
thanks @sorki that’s what I copied before posting here and it appears to do something during a rebuild but I can’t seem to see /dev/spi I’m probably just applying the config wrong is my guess. but I see this during rebuild (using latest kernel as well (all this in an attempt to get some silly epaper HAT working)):
Applying overlay spi to bcm2837-rpi-cm3-io3.dtb... ok
Applying overlay spi to bcm2837-rpi-3-b.dtb... ok
Applying overlay spi to bcm2711-rpi-4-b.dtb... ok
Applying overlay spi to bcm2711-rpi-400.dtb... ok
Applying overlay spi to bcm2837-rpi-3-a-plus.dtb... ok
Applying overlay spi to bcm2837-rpi-zero-2-w.dtb... ok
Applying overlay spi to bcm2837-rpi-3-b-plus.dtb... ok
Skipping overlay spi: incompatible with imx8mm-venice-gw73xx-0x-rpidsi.dtb
Skipping overlay spi: incompatible with imx8mp-venice-gw74xx-rpidsi.dtb
Skipping overlay spi: incompatible with imx8mm-venice-gw72xx-0x-rpidsi.dtb
Skipping overlay spi: incompatible with msm8996pro-xiaomi-scorpio.dtb
created 6803 symlinks in user environment
so I assumed it was working but I really have no idea what I’m doing
@rjpc did you ever get this working?
I also see my SPI overlay being applied to all the DTBs but the spidev devices don’t show up. Even after adding boot.kernelModules = [ "spi_bcm2835" "spidev" ]; to force the SPI modules to be run, when I lsmod I see them showing up but the ref/use count is 0 and the /dev/spidev* devices don’t exist.
@jhollowe@rjpc: I had similar problems but managed to get it to work. Might be a different issue, but just in case, here’s a quick description what caused my problems:
I was struggling with getting /dev/spidev* devices via device tree overlays using the mainline kernel, even though lsmod showed both spi_bcm2835 and spidev as being loaded. In the end, it turned out to be caused by having the wrong compatible string in the spidev@... devices. In particular, many dts overlays one finds online (like this one which was also linked in this thread) contain the lines
(To be clear: Some other comments in this thread already had links that pointed towards the same fix, but it just took me quite a bit to figure that out…)
This wasn’t the case before - the kernel just issued a loud warning but continued happily, which is why I didn’t remember my kernel patch adding back spidev to the list of compatible devices (that was optional as it just removed the warning message but is required now).