diff --git a/docs/files/fan/4_Wire_PWM_Spec.pdf b/docs/files/fan/4_Wire_PWM_Spec.pdf new file mode 100755 index 0000000..10d2186 Binary files /dev/null and b/docs/files/fan/4_Wire_PWM_Spec.pdf differ diff --git a/docs/img/hardware/fan_connector.png b/docs/img/hardware/fan_connector.png new file mode 100755 index 0000000..00990ed Binary files /dev/null and b/docs/img/hardware/fan_connector.png differ diff --git a/docs/img/hardware/fan_control_schematic.png b/docs/img/hardware/fan_control_schematic.png new file mode 100755 index 0000000..8fdfb11 Binary files /dev/null and b/docs/img/hardware/fan_control_schematic.png differ diff --git a/docs/img/hardware/fan_duty_cycle_formula.png b/docs/img/hardware/fan_duty_cycle_formula.png new file mode 100755 index 0000000..694f747 Binary files /dev/null and b/docs/img/hardware/fan_duty_cycle_formula.png differ diff --git a/docs/img/hardware/fan_new_photo.jpg b/docs/img/hardware/fan_new_photo.jpg new file mode 100755 index 0000000..01f0186 Binary files /dev/null and b/docs/img/hardware/fan_new_photo.jpg differ diff --git a/docs/img/hardware/fan_old_photo.jpg b/docs/img/hardware/fan_old_photo.jpg new file mode 100755 index 0000000..24c6503 Binary files /dev/null and b/docs/img/hardware/fan_old_photo.jpg differ diff --git a/docs/img/hardware/fan_speed_comparison.png b/docs/img/hardware/fan_speed_comparison.png new file mode 100755 index 0000000..8b7546c Binary files /dev/null and b/docs/img/hardware/fan_speed_comparison.png differ diff --git a/docs/img/hardware/fan_speed_graph_new_fan.png b/docs/img/hardware/fan_speed_graph_new_fan.png new file mode 100755 index 0000000..5646b33 Binary files /dev/null and b/docs/img/hardware/fan_speed_graph_new_fan.png differ diff --git a/docs/img/hardware/fan_speed_graph_new_fan_linux.png b/docs/img/hardware/fan_speed_graph_new_fan_linux.png new file mode 100755 index 0000000..55bd68e Binary files /dev/null and b/docs/img/hardware/fan_speed_graph_new_fan_linux.png differ diff --git a/docs/img/hardware/fan_speed_graph_old_fan.png b/docs/img/hardware/fan_speed_graph_old_fan.png new file mode 100755 index 0000000..5975246 Binary files /dev/null and b/docs/img/hardware/fan_speed_graph_old_fan.png differ diff --git a/docs/img/hardware/fan_speed_graph_old_fan_linux.png b/docs/img/hardware/fan_speed_graph_old_fan_linux.png new file mode 100755 index 0000000..413da42 Binary files /dev/null and b/docs/img/hardware/fan_speed_graph_old_fan_linux.png differ diff --git a/docs/img/hardware/fan_type_a_curve.jpg b/docs/img/hardware/fan_type_a_curve.jpg new file mode 100755 index 0000000..b8baa00 Binary files /dev/null and b/docs/img/hardware/fan_type_a_curve.jpg differ diff --git a/docs/img/hardware/fan_type_b_curve.jpg b/docs/img/hardware/fan_type_b_curve.jpg new file mode 100755 index 0000000..89cbf68 Binary files /dev/null and b/docs/img/hardware/fan_type_b_curve.jpg differ diff --git a/docs/img/hardware/fan_type_c_curve.jpg b/docs/img/hardware/fan_type_c_curve.jpg new file mode 100755 index 0000000..c542b8e Binary files /dev/null and b/docs/img/hardware/fan_type_c_curve.jpg differ diff --git a/docs/img/hardware/pwm_duty_cycle_graph.png b/docs/img/hardware/pwm_duty_cycle_graph.png new file mode 100644 index 0000000..c53ea8b Binary files /dev/null and b/docs/img/hardware/pwm_duty_cycle_graph.png differ diff --git a/docs/pwm.md b/docs/pwm.md index 82f990c..25dc255 100644 --- a/docs/pwm.md +++ b/docs/pwm.md @@ -1,2 +1,361 @@ +!!! warning + Always POWER OFF the system before plug/unplug the fan. Failed to do so could damage the controlling GPIO due to power surge. + +## PWM Introduction + +PWM, or pulse width modulation is a technique which allows us to adjust the average value of the voltage that’s going to the electronic device by varying duty cycle of the power at a fast rate. + +The term *duty cycle* describes the proportion of 'on' time to the regular interval or 'period' of time; a low duty cycle corresponds to low power, because the power is off for most of the time. Duty cycle is expressed in percent, 100% being fully on. When a digital signal is on half of the time and off the other half of the time, the digital signal has a duty cycle of 50% and resembles a "square" wave. When a digital signal spends more time in the on state than the off state, it has a duty cycle of >50%. When a digital signal spends more time in the off state than the on state, it has a duty cycle of <50%. Here is a pictorial that illustrates these three scenarios: + +![PWM duty cycle](/img/hardware/pwm_duty_cycle_graph.png) + +## PWM Fan Implementation + +### Type A + +![Type A Curve](/img/hardware/fan_type_a_curve.jpg) + +### Type B + +![Type B Curve](/img/hardware/fan_type_b_curve.jpg) + +### Type C + +![Type C Curve](/img/hardware/fan_type_c_curve.jpg) + +## Helios4 Fan Control Schematic + +![Helios4 Fan control](/img/hardware/fan_control_schematic.png) + + +| Description | Connector J10 | J17 | Remarks | +|-----------|---------|-----------|---------| +| PWM pin | gpio41 | gpio55 | 3.3V pull up fan **ONLY**! Early generation of 4-wire pwm fan may use 5V pull-up | +| SENSE pin | gpio43 | gpio48 | SENSE pin is not used yet | +| PWM Frequency | 25 kHz | 25 kHz | defined in device tree | + +## Bundled Fan + +![Fan Connector](/img/hardware/fan_connector.png) + +Connector Pinout + +| Pin | Function | Wire Color | +|-----|----------|------------| +| 1 | GND | Black | +| 2 | 12V | Red | +| 3 | Sense | Yellow | +| 4 | Control | Blue | + + +### Old Fan (Batch 1) + +![Old Fan](/img/hardware/fan_old_photo.jpg) + +Fan Specification + +| Parameter | Value | Unit | Remarks | +|---------------|----------|------|---------| +| Maximum Speed | 4200 | RPM | @ duty cycle 98% | +| Minimum Speed | 1200 | RPM | @ duty cycle 24% | +| Shut off | No | | Not Supported | +| Implementation Type | A | | | + +![Old Fan Speed Graph](/img/hardware/fan_speed_graph_old_fan.png) + !!! info - Coming soon. + Duty cycle data is converted from Linux PWM + +### New Fan (Batch 2) + +![New Fan](/img/hardware/fan_new_photo.jpg) + +Fan Specification + +| Parameter | Value | Unit | Remarks | +|---------------|----------|------|---------| +| Maximum Speed | 4200 | RPM | @ duty cycle 98% | +| Minimum Speed | 400 | RPM | @ duty cycle 10% | +| Shut off | Yes | | duty cycle <= 5.5% and restart @ duty cycle > 9% | +| Implementation Type | C | | | + +![New Fan Speed Graph](/img/hardware/fan_speed_graph_new_fan.png) + +!!! info + Duty cycle data is converted from Linux PWM + +### Fan Speed Comparison + +![Fan Speed Graph](/img/hardware/fan_speed_comparison.png) + + +## Helios4 Temperature Sensors + +### CPU Thermal Sensor + +Armada 388 incorporates a Thermal Management engine for monitoring die temperature. It includes an on-die analog-to-digital thermal sensor, that is used to determine when the maximum specified processor junction temperature has been reached. + +### Ethernet PHY Thermal Sensor + +Helios4's **10/100/1000 BASE-T PHY Tranceiver** ([Marvell 88E1512 Datasheet](http://www.marvell.com/documents/eoxwrbluvwybgxvagkkf/)) features an internal temperature sensor. The sensor reports the die temperature and is updated approximately once per second. + +### Board Temp Sensor + +Helios4 has a **Digital Temperature Sensor with 2‐wire Interface** ([NCT75 Datasheet](https://www.onsemi.com/pub/Collateral/NCT75-D.PDF)), located on bottom side of the board. It is used to read ambient temperature. + + +## PWM Fan Control under Linux + +Linux use 8-bit integer to represent duty cycle. PWM value 0 represent 0% duty cycle and PWM value 255 represent 100% duty cycle. + +![Duty Cycle Formula](/img/hardware/fan_duty_cycle_formula.png) + +Below graphs are bundled fan speed vs pwm value instead of duty cycle. + +![Old Fan Speed Graph](/img/hardware/fan_speed_graph_old_fan_linux.png) + +![New Fan Speed Graph](/img/hardware/fan_speed_graph_new_fan_linux.png) + +Currently Linux gpio-mvebu driver does not allow more than 1 PWM under the same bank. Helios4 uses 2 PWM under same bank therefore [this patch](https://raw.githubusercontent.com/armbian/build/master/patch/kernel/mvebu-next/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch) needs to be applied to kernel source to remove the restriction. + +### Using SYSFS interface + +Linux export the fan control mechanism to SYSFS under hwmon class. +List of devices can be checked under /sys/class/hwmon + +``` +ls -l /sys/class/hwmon/ +total 0 +lrwxrwxrwx 1 root root 0 Nov 7 07:23 hwmon0 -> ../../devices/platform/soc/soc:internal-regs/f1072004.mdio/mdio_bus/f1072004.mdio-mii/f1072004.mdio-mii:00/hwmon/hwmon0 +lrwxrwxrwx 1 root root 0 Nov 7 07:23 hwmon1 -> ../../devices/virtual/hwmon/hwmon1 +lrwxrwxrwx 1 root root 0 Nov 7 07:23 hwmon2 -> ../../devices/platform/j10-pwm/hwmon/hwmon2 +lrwxrwxrwx 1 root root 0 Nov 7 07:23 hwmon3 -> ../../devices/platform/j17-pwm/hwmon/hwmon3 +lrwxrwxrwx 1 root root 0 Nov 7 07:23 hwmon4 -> ../../devices/platform/soc/soc:internal-regs/f1011000.i2c/i2c-0/0-004c/hwmon/hwmon4 + +``` + +!!! info + The numbering may different from above example output. It depends on whether the driver built as kernel module or built-in, device initialization order. Take this as consideration when using [fancontrol](#fancontrol-automated-software-based-fan-speed-regulation) + +To identify which hwmon belong to fan, look for *j10-pwm* and *j17-pwm*. On above example + +``` +hwmon2 -> ../../devices/platform/j10-pwm/hwmon/hwmon2 +hwmon3 -> ../../devices/platform/j17-pwm/hwmon/hwmon3 +``` + +To read current PWM +``` +cat /sys/class/hwmon2/pwm1 +cat /sys/class/hwmon3/pwm1 +``` + +To set PWM +``` +echo NEW_PWM_VALUE > /sys/class/hwmon2/pwm1 +echo NEW_PWM_VALUE > /sys/class/hwmon3/pwm1 +``` + +### Fancontrol - automated software based fan speed regulation + +fancontrol is a shell script for use with lm_sensors. It reads its configuration from a file, then calculates fan speeds from temperatures and sets the corresponding PWM outputs to the computed values. + +fancontrol include *pwmconfig* script to create a configuration file but it can not be used in Helios4. + +#### Configuration File + +fancontrol uses **/etc/fancontrol** as configuration file. Below is an example configuration to control fan speed on Helios4. + +``` +# Helios4 PWM Fan Control Configuration +# Temp source : armada_thermal sensor +INTERVAL=10 +DEVPATH=hwmon2=devices/platform/j10-pwm hwmon3=devices/platform/j17-pwm hwmon4=devices/platform/soc/soc:internal-regs/f1011000.i2c/i2c-0/0-004c +DEVNAME=hwmon1=armada_thermal +FCTEMPS=hwmon2/pwm1=hwmon1/temp1_input hwmon3/pwm1=hwmon1/temp1_input +MINTEMP=hwmon2/pwm1=70 hwmon3/pwm1=70 +MAXTEMP=hwmon2/pwm1=90 hwmon3/pwm1=90 +MINSTART=hwmon2/pwm1=20 hwmon3/pwm1=20 +MINSTOP=hwmon2/pwm1=29 hwmon3/pwm1=29 +MINPWM=0 +``` + +INTERVAL + +This variable defines at which interval in seconds the main loop of fancontrol will be executed + +DEVPATH + +Maps hwmon class devices to physical devices. This lets fancontrol check that the configuration file is still up-to-date. + +It expect the **hwmonN** as symlink to **devices/*** + +DEVNAME + +Records hwmon class device names. This lets fancontrol check that the configuration file is still up-to-date. + +Since **armada_thermal** does not create symlink, use *DEVNAME* instead of *DEVPATH* + +FCTEMPS + +Maps PWM outputs to temperature sensors so fancontrol knows which temperature sensors should be used for calculation of new values for the corresponding PWM outputs. + +Fans (**hwmon2** & **hwmon3**) are controlled based on CPU thermal sensor (**hwmon1**) reading. + +MINSTART + +Sets the minimum speed at which the fan begins spinning. You should use a safe value to be sure it works, even when the fan gets old. + +New bundled fan restart at 15, added 5 for safety (in case of aging fan) give us **20**. The value does not affect old bundle fan. + +MINSTOP + +The minimum speed at which the fan still spins. Use a safe value here, too. + +New bundled fan stopped at 24, added 5 for safety (in case of aging fan) give us **29**. The value does not affect old bundle fan. + +----- + +*Following settings can be adjusted by user to tweak further.* + +MINTEMP + +The temperature below which the fan gets switched to minimum speed. + +Fans (hwmon2 & hwmon3) runs in minimum speed if the CPU temperature below **70** degree C. + +MAXTEMP + +The temperature over which the fan gets switched to maximum speed. + +Fans (hwmon2 & hwmon3) runs in maximum speed if the CPU temperature above **90** degree C. + +MINPWM + +The PWM value to use when the temperature is below MINTEMP. Typically, this will be either 0 if it is OK for the fan to plain stop, or the same value as MINSTOP if you don't want the fan to ever stop. If this value isn't defined, it defaults to 0 (stopped fan). + +Set minimum PWM value to **0**. On new bundled fan, it would stopped the fan while on old bundled fan it would run in minimal speed. + +!!! note + Since hwmon order can be changed between kernel version or even between reboot, on Armbian we use udev rules as workaround. The rules can be found from [here](https://raw.githubusercontent.com/armbian/build/master/packages/bsp/helios4/90-helios4-hwmon.rules) and the configuration file can be found [here](https://raw.githubusercontent.com/armbian/build/master/packages/bsp/helios4/fancontrol_pwm-fan-mvebu-next.conf) + + +### Thermal Zone on Device Tree + +Linux provide Thermal Framework to do thermal management. By using this method to control the fan speed, no userspace such as [fancontrol](#fancontrol-automated-software-based-fan-speed-regulation) is required. + +Below are device tree nodes that can be added to Helios4 device tree to make use of Linux Thermal Framework. + +``` +/ { + ... + + fan1: j10-pwm { + compatible = "pwm-fan"; + pwms = <&gpio1 9 40000>; /* Target freq:25 kHz */ + cooling-min-state = <0>; + cooling-max-state = <3>; + #cooling-cells = <2>; + cooling-levels = <0 25 128 255>; + }; + + fan2: j17-pwm { + compatible = "pwm-fan"; + pwms = <&gpio1 23 40000>; /* Target freq:25 kHz */ + cooling-min-state = <0>; + cooling-max-state = <3>; + #cooling-cells = <2>; + cooling-levels = <0 25 128 255>; + }; + + thermal-zones { + microsom_thermal: microsom-thermal { + thermal-sensors = <&thermal>; + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + trips { + cpu_active: cpu_active { + /* millicelsius */ + temperature = <70000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_alert: cpu_alert { + /* millicelsius */ + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_crit: cpu-crit { + /* millicelsius */ + temperature = <115000>; + hysteresis = <5000>; + type = "critical"; + }; + }; + }; + + board_thermal: board-thermal { + thermal-sensors = <&temp_sensor>; + polling-delay-passive = <0>; /* milliseconds */ + polling-delay = <1500>; /* milliseconds */ + trips { + board_active: board-active { + /* millicelsius */ + temperature = <40000>; + hysteresis = <2000>; + type = "active"; + }; + + board_alert: board-alert { + /* millicelsius */ + temperature = <60000>; + hysteresis = <2000>; + type = "hot"; + }; + + board_critical: board-critical { + /* millicelsius */ + temperature = <70000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&board_active>; + cooling-device = <&fan1 THERMAL_NO_LIMIT 2>, + <&fan2 THERMAL_NO_LIMIT 2>; + }; + map1 { + trip = <&board_alert>; + cooling-device = <&fan1 2 THERMAL_NO_LIMIT>, + <&fan2 2 THERMAL_NO_LIMIT>; + }; + }; + }; + }; + ... +}; + +&temp_sensor { + #thermal-sensor-cells = <0>; +}; +``` + +!!! info + Currently *armada_thermal* driver ([CPU Thermal Sensor](#cpu-thermal-sensor)) does not support thermal-zone binding in device tree, therefore it can not be used as thermal-sensor. + + +## References + +[Pulse-width modulation](https://en.wikipedia.org/wiki/Pulse-width_modulation) + +[4-Wire Pulse Width Modulation (PWM) Controlled Fans Specification rev. 1.3](/files/fan/4_Wire_PWM_Spec.pdf) + +[fancontrol man page](https://linux.die.net/man/8/fancontrol) + +[Linux Thermal Framework Device Tree descriptor](https://www.kernel.org/doc/Documentation/devicetree/bindings/thermal/thermal.txt)