NixOS / nixos-hardware

A collection of NixOS modules covering hardware quirks.
Creative Commons Zero v1.0 Universal
1.74k stars 550 forks source link

Raspberry Pi 4B: How to configure poe-hat? #910

Open astr0n8t opened 2 months ago

astr0n8t commented 2 months ago

I'm a bit of a nix noob I must admit, but I was trying to configure the Raspberry Pi PoE hat so that the thermal trips are a little more sane. Typically this is done with the following in /boot/firmware/config.txt :

dtparam=poe_fan_temp0=50000
dtparam=poe_fan_temp1=60000
dtparam=poe_fan_temp2=70000
dtparam=poe_fan_temp3=80000

but while I see the override values in the overlay:

              __overrides__ {
                poe_fan_temp0 =     <&trip0>,"temperature:0";
                poe_fan_temp0_hyst =    <&trip0>,"hysteresis:0";
                poe_fan_temp1 =     <&trip1>,"temperature:0";
                poe_fan_temp1_hyst =    <&trip1>,"hysteresis:0";
                poe_fan_temp2 =     <&trip2>,"temperature:0";
                poe_fan_temp2_hyst =    <&trip2>,"hysteresis:0";
                poe_fan_temp3 =     <&trip3>,"temperature:0";
                poe_fan_temp3_hyst =    <&trip3>,"hysteresis:0";
                i2c =           <0>, "+5+6",
                      <&fwpwm>,"status=disabled",
                      <&i2c_bus>,"status=okay",
                      <&poe_mfd>,"status=okay",
                      <&fan>,"pwms:0=",<&poe_mfd_pwm>;
              };

Changing the values in the config.txt doesn't work, and I must admit I have failed googling finding a way to configure these apart from my current solution which is to make a copy of the poe-hat dts text and apply a modified version with my custom values instead of the one in this repo.

I'd prefer to use the one provided by this repo if possible. Is there a better way than how I am currently doing this? Or is it just not possible to modify dtparams when using these overlays?

astr0n8t commented 1 month ago

To add to this, I'm now using a custom overlay that I hacked together that works with the upstream Linux kernel provided by pkgs.linuxPackages_latest after I encountered missing kernel config options used for rpi4 kernel

Here's my overlay:

/*
* Overlay for the Raspberry Pi POE HAT.
*/
/dts-v1/;
/plugin/;

/ {
  compatible = "brcm,bcm2711";

  fragment@0 {
    target-path = "/";
    __overlay__ {
      fan: pwm-fan {
        compatible = "pwm-fan";
        cooling-levels = <0 1 10 100 255>;
        #cooling-cells = <2>;
        pwms = <&fwpwm 0 80000>;
      };
    };
  };

  fragment@1 {
    target = <&cpu_thermal>;
    __overlay__ {
      polling-delay = <2000>; /* milliseconds */
      trips {
        trip0: trip0 {
          temperature = <50000>;
          hysteresis = <2000>;
          type = "active";
        };
        trip1: trip1 {
          temperature = <60000>;
          hysteresis = <2000>;
          type = "active";
        };
        trip2: trip2 {
          temperature = <70000>;
          hysteresis = <2000>;
          type = "active";
        };
        trip3: trip3 {
          temperature = <80000>;
          hysteresis = <5000>;
          type = "active";
        };
      };
      cooling-maps {
        map0 {
          trip = <&trip0>;
          cooling-device = <&fan 0 1>;
        };
        map1 {
          trip = <&trip1>;
          cooling-device = <&fan 1 2>;
        };
        map2 {
          trip = <&trip2>;
          cooling-device = <&fan 2 3>;
        };
        map3 {
          trip = <&trip3>;
          cooling-device = <&fan 3 4>;
        };
      };
    };
  };

  fragment@2 {
    target = <&firmware>;
    __overlay__ {
      fwpwm: pwm {
        compatible = "raspberrypi,firmware-poe-pwm";
        #pwm-cells = <2>;
      };
    };
  };

  fragment@3 {
    target = <&i2c0>;
    i2c_bus: __overlay__ {
      #address-cells = <1>;
      #size-cells = <0>;

      poe_mfd: poe@51 {
        compatible = "raspberrypi,poe-core";
        reg = <0x51>;
        status = "disabled";

        poe_mfd_pwm: poe_pwm@f0 {
          compatible = "raspberrypi,poe-pwm";
          reg = <0xf0>;
          status = "okay";
          #pwm-cells = <2>;
        };
      };
    };
  };
};

Here's the relevant nix config to apply:

  hardware = {
    raspberry-pi."4".apply-overlays-dtmerge.enable = true;
    deviceTree = {
      enable = true;
      filter = "bcm2711-rpi-4*.dtb";
      overlays = [
        { name = "rpi-poe"; dtsFile = ../overlays/rpi-poe.dts; }
      ];
    };
  };
astr0n8t commented 1 month ago

Also, I've since learned that the reason the dtparams don't work anymore is because nixos applies the device trees at build time whereas default raspbian does it every boot. So the only way to make this a bit more extensible would be to add nix configuration variables either added to the overlay or somehow implemented at apply time