Added PWM page

This commit is contained in:
Aditya Prayoga 2018-11-14 02:14:32 +08:00
parent ce86978ad2
commit 96b023ad38
16 changed files with 360 additions and 1 deletions

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View file

@ -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 thats 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 !!! 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 2wire 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)