turny: fix SPI/GPIO config for newer kernels
- Add complete config.txt settings with u-boot boot lines + spi=on - Override sdImage.populateFirmwareCommands to use configtxt module output - Mount firmware partition and add activation script to sync config.txt - Load spi_bcm2835 and bcm2835_gpiomem kernel modules - Add udev rule for gpiomem subsystem (not just gpio) - Relax ProtectKernelTunables so service can access GPIO - Update turny flake input to rppal-based CS pin fix
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
ssh,
|
||||
config,
|
||||
inputs,
|
||||
@@ -57,10 +58,10 @@ in
|
||||
# Select internationalisation properties.
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||
# Define a user account. Don't forget to set a password with 'passwd'.
|
||||
users.users.jokke = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||
extraGroups = [ "wheel" ]; # Enable 'sudo' for the user.
|
||||
packages = [ pkgs.nh ];
|
||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
||||
initialPassword = "changeme";
|
||||
@@ -74,7 +75,7 @@ in
|
||||
wget
|
||||
htop
|
||||
git
|
||||
inputs.turny.packages.${stdenv.hostPlatform.system}.default
|
||||
alsa-utils
|
||||
];
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
@@ -88,11 +89,158 @@ in
|
||||
allInterfaces = [ "ssh" ];
|
||||
};
|
||||
|
||||
# Enable audio (ALSA)
|
||||
hardware.alsa.enable = true;
|
||||
|
||||
# Complete config.txt settings: boot-critical u-boot lines plus SPI enable.
|
||||
# The configtxt module generates the full config.txt, overriding the
|
||||
# hardcoded one in sd-image-aarch64.nix which ignores these settings.
|
||||
hardware.raspberry-pi.configtxt.settings = {
|
||||
pi3 = {
|
||||
kernel = "u-boot-rpi3.bin";
|
||||
core_freq = 250;
|
||||
};
|
||||
pi02 = {
|
||||
kernel = "u-boot-rpi3.bin";
|
||||
};
|
||||
pi4 = {
|
||||
kernel = "u-boot-rpi4.bin";
|
||||
enable_gic = true;
|
||||
armstub = "armstub8-gic.bin";
|
||||
};
|
||||
all = {
|
||||
arm_64bit = true;
|
||||
enable_uart = true;
|
||||
avoid_warnings = true;
|
||||
dtparam = [
|
||||
"audio=on"
|
||||
"spi=on"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Use the configtxt module's generated config.txt when building SD images
|
||||
sdImage.populateFirmwareCommands = let
|
||||
inherit (config.hardware.raspberry-pi.configtxt) file;
|
||||
in ''
|
||||
(cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/firmware/)
|
||||
|
||||
cp ${file} firmware/config.txt
|
||||
|
||||
cp ${pkgs.ubootRaspberryPi3_64bit}/u-boot.bin firmware/u-boot-rpi3.bin
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-2-b.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-3-b.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-3-b-plus.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-cm3.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-zero-2.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-zero-2-w.dtb firmware/
|
||||
|
||||
cp ${pkgs.ubootRaspberryPi4_64bit}/u-boot.bin firmware/u-boot-rpi4.bin
|
||||
cp ${pkgs.raspberrypi-armstubs}/armstub8-gic.bin firmware/armstub8-gic.bin
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-4-b.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-400.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-cm4.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-cm4s.dtb firmware/
|
||||
'';
|
||||
|
||||
# Load SPI and GPIO kernel modules so /dev/spidev* and /dev/gpiomem exist
|
||||
boot.kernelModules = [
|
||||
"spi_bcm2835"
|
||||
"bcm2835_gpiomem"
|
||||
];
|
||||
|
||||
# Use the firmware-passed device tree (with dtparam/dtoverlay applied)
|
||||
# instead of u-boot loading a fresh DTB from FDTDIR
|
||||
boot.loader.generic-extlinux-compatible.useGenerationDeviceTree = false;
|
||||
|
||||
# Mount the firmware partition so config.txt is accessible and can be
|
||||
# updated on deploys. The sd-image module defaults to noauto; we need it
|
||||
# mounted so the activation script can sync config.txt.
|
||||
fileSystems."/boot/firmware".options = [
|
||||
"nofail"
|
||||
"defaults"
|
||||
];
|
||||
|
||||
# Sync the generated config.txt to the firmware partition on each deploy
|
||||
# so dtparam/dtoverlay changes take effect without reflashing the SD card.
|
||||
system.activationScripts.syncConfigTxt = {
|
||||
text = ''
|
||||
if mountpoint -q /boot/firmware; then
|
||||
cp -f ${config.hardware.raspberry-pi.configtxt.file} /boot/firmware/config.txt
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Turny service
|
||||
systemd.services.turny = {
|
||||
description = "Turny Spotify RFID Controller";
|
||||
documentation = [ "https://github.com/repomaa/turny" ];
|
||||
after = [
|
||||
"network.target"
|
||||
"sound.target"
|
||||
];
|
||||
wants = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = lib.getExe inputs.turny.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
User = "turny";
|
||||
Group = "turny";
|
||||
WorkingDirectory = "/var/lib/turny";
|
||||
Restart = "always";
|
||||
RestartSec = 10;
|
||||
RestartPreventExitStatus = 23;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ReadWritePaths = [ "/var/lib/turny" ];
|
||||
ProtectKernelTunables = false;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
LimitNOFILE = 1024;
|
||||
MemoryAccounting = true;
|
||||
MemoryMax = "100M";
|
||||
StandardOutput = "journal";
|
||||
StandardError = "journal";
|
||||
SyslogIdentifier = "turny";
|
||||
};
|
||||
environment = {
|
||||
RUST_LOG = "info";
|
||||
RUST_BACKTRACE = "1";
|
||||
};
|
||||
};
|
||||
|
||||
users.users.turny = {
|
||||
isSystemUser = true;
|
||||
group = "turny";
|
||||
extraGroups = [
|
||||
"gpio"
|
||||
"spi"
|
||||
"audio"
|
||||
];
|
||||
home = "/var/lib/turny";
|
||||
createHome = true;
|
||||
};
|
||||
users.groups.turny = { };
|
||||
users.groups.gpio = { };
|
||||
users.groups.spi = { };
|
||||
|
||||
# Udev rules for GPIO and SPI access
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660"
|
||||
SUBSYSTEM=="gpiomem", GROUP="gpio", MODE="0660"
|
||||
SUBSYSTEM=="gpio", ACTION=="add", RUN+="${lib.getExe' pkgs.coreutils "sh"} -c 'chgrp gpio /sys/class/gpio/export /sys/class/gpio/unexport; chmod 0660 /sys/class/gpio/export /sys/class/gpio/unexport'"
|
||||
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
|
||||
'';
|
||||
|
||||
# This value determines the NixOS release from which the default
|
||||
# settings for stateful data, like file locations and database versions
|
||||
# on your system were taken. It's perfectly fine and recommended to leave
|
||||
# settings for stateful data, like user locations and database versions
|
||||
# on the system were taken. It's perfectly fine and recommended to leave
|
||||
# this value at the release version of the first install of this system.
|
||||
# Before changing this value read the documentation for this option
|
||||
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||
system.stateVersion = "25.05"; # Did you read the comment?
|
||||
|
||||
sdImage.compressImage = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user