NixOS + RPi4 + UEFI (U-Boot), devicetree wonkiness?

Hey there!

I’ve been struggling with some devicetree strangeness for a couple of days and I’m running out of ideas—figured I’d turn to some experts.

I have unstable running successfully on a raspberry pi 4 booted via UEFI (Tow-Boot) off of USB with the rpi-flavored kernel (linuxPackages_rpi4).

I’ve tried to enable an overlay to get the PoE Hat fan running but I’m having difficulty.

I can see that the overlay appears to have been merged correctly when I inspect the dtb in /run/current-system/dtbs/broadcom/bcm2711-rpi-4-b.dtb but the relevant /proc entries are not there (for example, the /proc/device-tree/thermal-zones/cpu-thermal/trips/* entries) which leads me to believe the system is mounting the firmware-provided dtb (from /boot/bcm2711-rpi-4-b.dts). If I copy the dtb file from the current-system to the boot partition, the /proc entries are created but the fans still aren’t spinning.

A quick lsmod shows the relevant module is registered but it’s not used by anything:

# lsmod
Module                  Size  Used by
... [snip] ...
pwm_raspberrypi_poe    16384  0

My understanding is too shallow to know what to try next but I feel like I’m very close. Anyone have any (much appreciated!) tips on where to go from here?

IIUC, hardware.deviceTree doesn’t do anything when you’re not booting with the boot.loader.generic-extlinux-compatible boot method, which is how the sd-image on hydra is configured. With UEFI you’re just doing a standard ole boot and the kernel is using whatever DTB is provided by the firmware or boot loader. Your boot loader (whether it’s grub or systemd-boot) probably isn’t providing one since NixOS doesn’t configure anything like that, so it’s probably just using whatever DTB Tow-Boot is providing.

1 Like

Thanks for the the info! Makes sense and confirms my (uninformed) suspicion. For posterity, I’m using systemd-boot with no additional devicetree config.

I’ll mess around with u-boot and tow-boot to see if I can get them to do the merge using the structure shipped with the rpi boot firmware.

I’m unclear why the merged dtb copied over didn’t result in a working fan despite the lsmod showing the module and /proc reflecting the structure with the poe-hat overlay. Think it’s another missing overlay or would there be some other thing (module? daemon? wizardry?) that is missing from the filesystem? I don’t know a ton about devicetrees and how the kernel uses them to accomplish things like spinning fans in response to a temp sensor. :slight_smile:

I think I made some progress but still not yet working.

It looks like the kernel module is attempting to load but failing. Seeing this in my dmesg output:

[   11.811696] raspberrypi-firmware soc:firmware: Request 0x00038049 returned status 0x80000001
[   11.811736] raspberrypi-poe-pwm soc:firmware:pwm: Failed to set duty cycle: -EINVAL
[   11.811748] pwm-fan pwm-fan: Failed to configure PWM: -22
[   11.811759] pwm-fan: probe of pwm-fan failed with error -22

That lead me to this thread in a Slackware forum which it looks like was resolved by rebuilding the kernel with a different config.

Got it by looking at the changes made by the slackware forum user. I just had to use a more recent rpi bootloader (grabbing the dat, bin, and elf files form the boot directory of the raspberrypi/firmware). Not sure that it would matter but I grabbed the same version that was supplied with the current* rpi linux kernel in nixpkgs.

Thanks again for your help, @ElvishJerricco!

1 Like

systemd-boot now supports device tree and overlays: Boot Loader Specification | UAPI Group Specifications. Need to be implemented in NixOS though.

1 Like

@box, would you mind sharing your config?

I’m planning to build a UEFI-based RPi image (with ZFS). Seeing an example might help me go faster.


I’ll put together a more detailed writeup this week but the short explanation is there was really nothing special in the config. I used tow-boot to boot the regular unstable LTS kernel aarch64 installer (regular old u-boot or the tianocore-based uefi firmware is undoubtedly fine too). Setup my partitions on the USB drive, created my zfs filesystems, etc. Regular nixos-install to generate the config/hardware-config. One addition the hardware-configuration was using the current rpi4-supported kernel nixpkgs knows about with boot.kernelPackages = pkgs.linuxPackages_rpi4 (though I wonder if I could get away with latest mainline that zfs supports: config.boot.zfs.package.latestCompatibleLinuxPackages).

I also made these changes to my config:

  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = false;
  boot.supportedFilesystems = [ "zfs" ];
  networking.hostId = "<random hostId>";

… because 1) I wanted to use systemd-boot, 2) u-boot/tow-boot cannot, in my experience, manipulate efivars once booted, and 3) to support zfs in the stage 1 loader.

That was it to get booted. I copied over the firmware dtb and dtbos from the firmware that matched the version used in the nixpkg rpi4 kernel (as mentioned above) which was enough to get the PoE Hat working (adding dtparam overrides in the boot partition config.txt worked at this point).

I’ll work up a step by step post shortly since a lot of this wasn’t clear to me when I started, and I’m considering writing an installer to automate all these stuff but not committing to that. :slight_smile:

1 Like