diff --git a/hosts/12kingdoms-shoukei/apple-silicon.nix b/hosts/12kingdoms-shoukei/apple-silicon.nix index b07eec47..3ef23c62 100644 --- a/hosts/12kingdoms-shoukei/apple-silicon.nix +++ b/hosts/12kingdoms-shoukei/apple-silicon.nix @@ -66,6 +66,37 @@ HibernateDelaySec = "5min"; }; + # Cap charging at 90%: the SMC's charge_control_end_threshold does not reliably survive a reboot, + # and a udev rule that writes it races the driver probe, so re-apply it from a boot-time service. + # TLP is not used for this: its macbook plugin still validates the 80-or-100 values of the older + # CHWA firmware and rejects anything else, while this machine's CHLS key takes any value. The + # driver ignores charge_control_start_threshold writes and derives it as end - 5. + systemd.services.apple-charge-limit = { + description = "Cap the battery charge at 90%"; + wantedBy = [ "multi-user.target" ]; + after = [ "systemd-modules-load.service" ]; + path = [ pkgs.coreutils ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = pkgs.writeShellScript "apple-charge-limit" '' + limit=90 # percent + node=/sys/class/power_supply/macsmc-battery/charge_control_end_threshold + # macsmc probes asynchronously, so retry briefly instead of racing the driver. + for _ in $(seq 1 30); do + if [ -e "$node" ] && echo "$limit" > "$node" 2>/dev/null && + [ "$(cat "$node")" = "$limit" ]; then + echo "battery charge capped at $limit%" + exit 0 + fi + sleep 1 + done + echo "battery charge cap: $(cat "$node" 2>/dev/null || echo "$node missing")" >&2 + exit 1 + ''; + }; + }; + # After adding this snippet, you need to restart the system for the touchbar to work. hardware.apple.touchBar = { enable = true;