Skip to content

Instantly share code, notes, and snippets.

@softminus
Created February 6, 2020 01:58
Show Gist options
  • Save softminus/651d898b3958be552e8d3c403c988fad to your computer and use it in GitHub Desktop.
Save softminus/651d898b3958be552e8d3c403c988fad to your computer and use it in GitHub Desktop.
Set minimum fan speed on Fujitsu/Kontron motherboards with Teutates BMC
#!/bin/bash
# Copyright (C) 2020 Kia
# Licensed under Zero Clause BSD License
if [[ $# -ne 3 ]]; then
echo "usage: $0 (BMC I2C BUS NUMBER) (FAN PAGE) (DUTY CYCLE FLOOR)"
echo ""
echo "BMC I2C BUS NUMBER can be found as follows"
echo "$ ls /sys/bus/i2c/devices/*/hwmon/hwmon*/fan1_input"
echo ""
echo "if the output of that command is:"
echo "/sys/bus/i2c/devices/7-0073/hwmon/hwmon4/fan1_input"
echo "that means that the I2C bus number is 7"
echo "Check /sys/module/ftsteutates/drivers/i2c\:ftsteutates/ to be sure"
echo ""
echo "FAN PAGE = 0x48 + index of fan"
echo "On my system, FAN PAGE can be (0x48, 0x49, 0x4a, 0x4b)"
echo ""
echo "DUTY CYCLE FLOOR can be any number from 0 to 255, but please"
echo "don't set it lower than it already is."
echo ""
echo "This tool asks the Teutates BMC (in a way that does not survive"
echo "reboots/power-cycles/shutdowns) to keep the PWM waveform that is"
echo "fed to the fan corresponding to FAN PAGE to have a duty cycle that"
echo "is greater or equal to (DUTY CYCLE FLOOR) / 255"
echo ""
echo "A fan that runs at MAX_RPM without a PWM signal (or with a DC PWM"
echo "signal) will never run slower than MAX_RPM * (DUTY CYCLE FLOOR) / 255"
echo ""
echo "#########################################################################"
echo " ☢CAUTION!!☢"
echo "The supplied I2C bus number MUST correspond to the bus where the"
echo "Teutates BMC lives on."
echo ""
echo "The supplied fan page must be between 0x48-0x4f inclusive and"
echo "must correspond to a fan in your system connected to the Teutates BMC."
echo ""
echo "Incorrectly specifying the I2C bus number or fan page may BRICK"
echo "or IRREVERSIBLY DESTROY your system!"
echo " ☢CAUTION!!☢"
echo "#########################################################################"
echo ""
echo "It is likely that this tool will not produce expected results if"
echo "SilentFanConfig-Manager has been run -- which writes fan config stuff"
echo "into nonvolatile storage. The aforementioned fan config stuff might"
echo "set a different set of control modes, causing the write to 0x86 to"
echo "not have the desired effect. I don't have the full Teutates"
echo "documentation, so i do not know any of the control laws are."
echo ""
echo "However, if you have access to SilentFanConfig-Manager, why do you even"
echo "need this?"
echo ""
echo "This tool has only been tested on a single motherboard:"
echo "FUJITSU /D3641-S1, BIOS V5.0.0.13 R1.7.0 for D3641-S1x"
echo "with FTS Teutates chip revision: 3.11"
echo ""
echo "FOR USE ONLY ON FUJITSU/KONTRON MOTHERBOARDS WITH TEUTATES BMC"
echo ""
exit 1
fi
case $2 in
0x48|0x49|0x4a|0x4b|0x4c|0x4d|0x4e|0x4f)
echo "supplied fan page is "$2
;;
*)
echo "INVALID FAN PAGE!!"
exit 2
;;
esac
set -e
echo -n "Testing for Teutates BMC presence... "
# test that we have a teutates bmc, ideally this modprobe fails otherwise
sudo modprobe ftsteutates
# but we need it not be loaded, so we can have the i2c bus to ourselves
sudo rmmod ftsteutates
echo "present"
# this lets us do i2cset
sudo modprobe i2c-dev
# switch the page for the fan in question. the user is responsible
# for making sure this is between 0x48 and 0x4f
echo "writing to the i2c bus; hope you gave us the correct one!"
sudo i2cset -y $1 0x73 0x7f $2
# set PWM duty cycle
sudo i2cset -y $1 0x73 0x86 $3
# set the page back to 0x00 just to be kind to whoever (the kernel module) talks with the BMC after us
sudo i2cset -y $1 0x73 0x7f 0x00
echo "writes done"
# let us look at our handiwork via sensors(1).
# be patient, i think the BMC only updates RPM every second or so
sudo modprobe ftsteutates
@dominikpaulus
Copy link

This is amazing, thanks a lot for doing this!

Looking at the documentation for the Teutates BMC, it seems that you are writing to undocumented control registers - the offset 0x86 is not documented in the official Fujitsu docs. Is that right? Where do you have these offsets from? Are there other points of the fan speed curve that one could modify, potentially? (E.g. fan max speed)
I'm thinking about patching the ftsteutates kernel driver to support fan control (at least locally), but it seems that the published documentation is insufficient for that... :(

@dominikpaulus
Copy link

I patched the "Teutates" BMC kernel driver to support rudimentary fan control: https://gist.github.com/dominikpaulus/278886a1955397972bf2ecdd80d69b42 - it's just writing the PWM speed to 0x86, i.e. doing the same thing as your script, except that it's in-kernel.

In principle, this works for me on a Fujitsu/Kontron D3644-B. However, the fan speed regulation is very slow (it takes ~1min for the fan to spin down from maximum speed to default speed after writing to the register). For that reason, fancontrol/pwmconfig is also complaining a bit (because it reacts too slowly to fan speed changes). So, my original question still stands - if you happen to have more knowledge about the BMC, that would be very much appreciated. But in the meantime, again, thanks for this script and the knowledge about the semantics of the 0x86 register :)!

@StancuFlorin
Copy link

StancuFlorin commented Jun 23, 2024

Hi @dominikpaulus

Nice work! Did you checked this datasheet? Any useful information there?

Specifications of the chip can be found at the Kontron FTP Server https://ftp.kontron.com/ (username = “anonymous”, no password required) under the following path:

/Services/Software_Tools/Linux_SystemMonitoring_Watchdog_GPIO/BMC-Teutates_Specification_V1.21.pdf

@dominikpaulus
Copy link

Yes, I did - unfortunately, the BMC specification published by Kontron/Fujitsu seems to be incomplete. The register used by @softminus' script above is not documented in the PDF you linked.

@totalizator
Copy link

No joy with Fujitsu D3646-S. I can see the fans but no speed change when playing with the script. I have tried all possible fan pages (0x48|0x49|0x4a|0x4b|0x4c|0x4d|0x4e|0x4f).

ftsteutates-i2c-0-73
Adapter: SMBus I801 adapter at efa0
fan2: 1440 RPM
fan3: 1560 RPM

Does it matter what I have configured in BIOS? Right now the fan control it's set to Auto (with the remaining options being Enhanced and Full). It's mind blowing that we can't simply set minimal fan speed there.

@dominikpaulus
Copy link

@totalizator : What happens if you write '255' to the duty cycle register? Do the fans spin up? If yes - the BMC might just pick a fan speed above the "minimum" duty cycle specified in the 0x86 register - which is very much plausible, the script controls the minimum fan speed and not the actual fan speed.

If it doesn't work - are you sure that you are using 4-pin PWM fans (and not 3-pin fans? Not sure if the board supports voltage regulation).

I'd love to have more control over the fan speed and potentially also be able to fully turn them off, but for that, someone would need to find more documentation about the Teutates chip :).
I asked the Kontron support about this, but unfortunately, they don't respond to inquiries from private customers. You could try asking the supplier that you bought the board from if they are able to provide additional documentation about the hardware, maybe anyone is more successful at this than I am...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment