FAN: coudln't stop on my cutom board

Our HW dropped FAN_DISABLE feature completely from design,just only FAN_PWM and FAN_TACH,and how can I control the FAN?

FAN:couldn’t get the regulator

If you look at the default dev board script “~nvidia/jetson_clocks.sh” (human readable bash) check out function “do_fan()”. The fan is normally “auto”, but running jetson_clocks.sh to max out simply sets to 255…always on at max. Auto is 0.

Try to echo the value you want (0 for automatic, 255 for always on, or some in-between value).

# View:
sudo cat /sys/kernel/debug/tegra_fan/target_pwm
# Set auto:
echo 0 > /sys/kernel/debug/tegra_fan/target_pwm
# Set an arbitrary value:
echo 128 > /sys/kernel/debug/tegra_fan/target_pwm
# Set max:
echo 255 > /sys/kernel/debug/tegra_fan/target_pwm

Hello @linuxdev,
In my case,

/sys/kernel/debug/tegra_fan/

isn’t available.
Is there any way to test the fan hardware independently?

If the installation is “ordinary” the file should be there. The file is a result of a driver being present. The implication is that the driver was removed or failed loading. Do you see any errors (something other than “ok”) from:

sha1sum -c /etc/nv_tegra_release

Was this flashed? Which version? See “head -n 1 /etc/nv_tegra_release”.

Output of

sha1sum -c /etc/nv_tegra_release
/usr/lib/aarch64-linux-gnu/libv4l/plugins/libv4l2_nvvideocodec.so: OK
/usr/lib/aarch64-linux-gnu/libv4l/plugins/libv4l2_nvvidconv.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvomx.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnveglstreamproducer.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvtx_helper.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvddk_vic.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libglx.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libargus_socketserver.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmmlite.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvddk_2d_v2.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvwinsys.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libargus.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmm.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvjpeg.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvexif.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvdc.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvavp.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvtestresults.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmm_utils.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvfnet.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvll.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcameratools.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvapputil.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnveglstream_camconsumer.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvrm.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcam_imageencoder.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvparser.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvtvmr.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvrm_gpu.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvtnr.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcamerautils.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvidia-egl-wayland.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvfnetstoredefog.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvodm_imager.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_utils.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcolorutil.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_video.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_image.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmm_contentpipe.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvimp.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvos.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvrm_graphics.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmedia.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvfnetstorehdfx.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvomxilclient.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcamlog.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmm_parser.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libscf.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvosd.so: OK
/usr/lib/xorg/modules/drivers/nvidia_drv.so: OK
/usr/lib/xorg/modules/extensions/libglx.so: OK

All of them seem to be OK.

Yes, I flashed it. I’m using an Auvidea J90 carrier board.

.# R28 (release), REVISION: 1.0, GCID: 9379712, BOARD: t186ref, EABI: aarch64, DATE: Thu Jul 20 07:59:31 UTC 2017

The carrier board changes require a different device tree. If the correct device tree was not used, then the driver would not be associated with the correct device or wiring details. Did you use a device tree specific to this carrier board?

Yeah, I did. It was working initially, but I was playing with my camera device tree file, and after one attempt, the fan stopped working.
How can I test if the fan hardware is okay, separately?

Without that device special file existing I don’t know of a software method of working with the fan. I have never looked at the fan voltage so I couldn’t tell you if there is a way to just apply external power to test. On the other hand, the device tree is 99.99% likely the cause of the failure. Instead of adjusting only the camera some other part of the device tree was also altered.

If there is a way for you to restore the original tree, and then make small additions for the camera while testing the fan file for existence at each step you would know for sure.

Alright, thank you.

It turned out to be a problem with my hardware as well. I tried with another fan, and it runs. The strange thing, however, is that on my carrier board, the

/sys/kernel/debug/tegra_fan/

is still not created, and I cannot control the fan.
If I connect it to the Dev Kit, though, I am able to control it.
Is there anything specific in the device tree files I can look for?

I’ve never looked at the details of fan setup, but odds are quite high that a driver is unable to work with the fan due to missing device tree changes for the different carrier board. If the driver uses a device tree from another carrier board chances are extremely high that the driver won’t ever load. No load implies the pseudo file in “/sys” won’t exist. You should explore the PINMUX spreadsheet and device tree changes which have to be edited for your alternate carrier board. I have not created a custom board before, but the combination of the PINMUX and device tree are definitely what you will need to change to get that file.

Just FYI, drivers tend to have a struct which works something like a constructor. When the driver loads it will set initial values for variables via the device tree. Should those variables allow correct load (which usually implies a valid hardware response for those values), then the driver will create that file. The variables are specific to various pins on the module and/or carrier board and if the function of those pins are not as expected, then the driver will fail. The device tree does not cause pins to change hardware function (the tree changes content in the driver on load), and so if the pins have not been set up via the PINMUX (which does change hardware function, but not drivers), then the tree can’t be correct because the hardware is something other than expected.

FYI, if you go here it will list PINMUX docs:
https://developer.nvidia.com/embedded/downloads#?search=pinmux

The PINMUX spreadsheet requires enabling macros, but basically you fill in the correct changes, and then a macro computes a file used during flash. Combined with a device tree edit which reflects that hardware configuration the pseudo file will appear upon driver load.

Ah, thank you. That was useful information.
So, I checked my carrier board reference sheet, and this is what it says for the fan:

On the dev kit
„fan disable“ is controlled by an I2C port expander line. On the J100 „fan disable“ is connected to
GPIO19_AUD_RST (through an inverting MOSFET). Pull the GPIO19 high to disable the fan (pin 4 becomes low).
A low or floating signal on GPIO19 will not disable the fan.

GPIO19_AUD_RST turns out to be GPIO 398, or (J,6)

I made the following changes to the device tree as per the Auvidea patches,:

fixed-regulators {
		vdd_fan: regulator@13 {
			gpio = <&tegra_main_gpio TEGRA_MAIN_GPIO(J, 6) GPIO_ACTIVE_LOW>;  //alternative gpio for auvidea carrier boards
		};
	};

	pwm_fan_shared_data: pfsd {
		status = "okay";
		num_resources = <0>;
		secret = <47>;
		active_steps = <10>;
		active_rpm = <0 1000 2000 3000 4000 5000 6000 7000 10000 11000>;
		rpm_diff_tolerance = <2>;
		active_rru = <40 2 1 1 1 1 1 1 1 1>;
		active_rrd = <40 2 1 1 1 1 1 1 1 1>;
		state_cap_lookup = <2 2 2 2 3 3 3 4 4 4>;
		pwm_period = <45334>;
		pwm_id = <4>;
		step_time = <100>; /* mesecs */
		state_cap = <7>;
		active_pwm_max = <256>;
		tach_period = <1000>;
		//pwm_gpio = <&tegra_aon_gpio TEGRA_AON_GPIO(V, 6) GPIO_ACTIVE_LOW>; /* TEGRA_MAIN_GPIO_PV6 */
		//pwm_gpio = <&tegra_main_gpio TEGRA_MAIN_GPIO(J, 6) GPIO_ACTIVE_LOW>; /* TEGRA_MAIN_GPIO_PJ6 */
	};
	pwm-fan {
		status = "okay";
		compatible = "pwm-fan";

		shared_data = <&pwm_fan_shared_data>;
		active_pwm = <0 80 120 160 255 255 255 255 255 255>;
	};

Now, on my carrier board, when I turn the power on, the fan initially runs, and once the jetson is fully booted, it stops.
However, the /sys/kernel/debug/tegra_fan still isn’t created.

If I run

dmesg | grep -i fan

This is what it shows:

[    0.000000] 	Build-time adjustment of leaf fanout to 64.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=6
[    0.344305] vdd-fan: 5000 mV 
[    2.764667] thermal thermal_zone8: Registering thermal zone thermal_zone8 for type thermal-fan-est
[    3.825349] FAN dev name: pwm-fan
[    4.002911] [<ffffffc0007b4648>] pwm_fan_probe+0xe8/0x9f0
[    4.057922] [<ffffffc0011085cc>] pwm_fan_driver_init+0x18/0x20
<b>[    4.092690] FAN:gpio request failed</b>
[    4.096678] pwm_fan_driver: probe of pwm-fan failed with error -22
[    7.606405] vdd-fan: disabling

Maybe the line in bold saying gpio request failed, is the cause of the error?

I run

cat /sys/kernel/debug/gpio

whose output is:

GPIOs 320-511, platform/2200000.gpio, tegra-gpio:
 gpio-381 (                    |reset_gpio          ) out lo    
 gpio-398 (                    |vdd-fan             ) out hi    
 gpio-412 (                    |vdd-usb0-5v         ) out lo    
 gpio-413 (                    |vdd-usb1-5v         ) out lo    
 gpio-420 (                    |eqos_phy_reset      ) out hi    
 gpio-421 (                    |eqos_phy_intr       ) in  hi    
 gpio-424 (                    |wlan_pwr            ) out hi    
 gpio-441 (                    |hdmi2.0_hpd         ) in  lo    
 gpio-444 (                    |wp                  ) in  hi    
 gpio-445 (                    |cd                  ) in  hi    
 gpio-446 (                    |en-vdd-sd           ) out lo    
 gpio-457 (                    |cam1-rst            ) out lo    
 gpio-479 (                    |external-connection:) in  lo    
 gpio-484 (                    |bt_ext_wake         ) out hi

It seems gpio-398 is created for the fan, so I am at a loss on what to do with this information

Seems like this is where the error occurs:

err = gpio_request(pwm_fan_gpio, "pwm-fan");
	if (err < 0) {
		pr_err("FAN:gpio request failed\n");
		err = -EINVAL;
		goto gpio_request_fail;
	} else {
		pr_info("FAN:gpio request success.\n");
	}

In the file linux/gpio.h, this is what I could find for the function gpio_request:

static inline int gpio_request(unsigned gpio, const char *label)
{
	return -ENOSYS;
}

Can someone point to which file has the definition for this function, or why this error could occur?

There is a lot I can’t answer about details for this alternate carrier board, but it is normal for the fan to initially have a short “blip” of activity on power on, and then stop (auto fan power is dependent upon temperature, and the temperature is usually too low for the fan to go active).

However, not having the device special file is an issue. One thought is that perhaps the function of a pin is being altered later during boot despite starting out correctly.

Another possibility is that some kernel option is changed and does not support export to “/sys” due to the change (in which case some mechanisms inside the kernel would still work for fan control, but control through “/sys” would not work).

It still sounds very much like some difference in setup due to this carrier board is not quite correct. What do you see from:

sudo find /sys -name '*fan*'

On an R28.2 TX2 with development carrier board I see this:

/sys/bus/platform/devices/pwm-fan
/sys/bus/platform/devices/thermal-fan-est
/sys/bus/platform/drivers/pwm_fan_driver
/sys/bus/platform/drivers/pwm_fan_driver/pwm-fan
/sys/bus/platform/drivers/therm-fan-est-driver
/sys/bus/platform/drivers/therm-fan-est-driver/thermal-fan-est
/sys/devices/pwm-fan
/sys/devices/fixed-regulators/fixed-regulators:regulator@13/regulator/regulator.28/pwm-fan-vdd-fan
/sys/devices/thermal-fan-est
/sys/firmware/devicetree/base/pwm-fan
/sys/firmware/devicetree/base/pwm-fan/vdd-fan-supply
/sys/firmware/devicetree/base/thermal-fan-est
/sys/kernel/debug/tegra_fan
/sys/kernel/debug/regulator/vdd-fan
/sys/kernel/debug/regulator/vdd-fan/pwm-fan-vdd-fan
/sys/module/rcutree/parameters/rcu_fanout_exact
/sys/module/rcutree/parameters/rcu_fanout_leaf

Knowing what is missing might narrow down some upstream requirement which is missing, e.g., a kernel config. I see some of this is under firmware, so perhaps the Auvidea board also has a firmware update (likely though this is just device tree and not really firmware in the stricter definition…the “/proc/device-tree/” directory is actually a symbolic link into “/sys”).

Hello,
When I run:

sudo find /sys -name '*fan*'

This is the output, I get on L4T V28.1:

/sys/bus/platform/devices/pwm-fan
/sys/bus/platform/devices/thermal-fan-est
/sys/bus/platform/drivers/pwm_fan_driver
/sys/bus/platform/drivers/therm-fan-est-driver
/sys/bus/platform/drivers/therm-fan-est-driver/thermal-fan-est
/sys/devices/pwm-fan
/sys/devices/fixed-regulators/fixed-regulators:regulator@13/regulator/regulator.19/pwm-fan-vdd-fan
/sys/devices/thermal-fan-est
/sys/firmware/devicetree/base/pwm-fan
/sys/firmware/devicetree/base/pwm-fan/vdd-fan-supply
/sys/firmware/devicetree/base/thermal-fan-est
/sys/kernel/debug/regulator/vdd-fan
/sys/kernel/debug/regulator/vdd-fan/pwm-fan-vdd-fan
/sys/module/rcutree/parameters/rcu_fanout_exact
/sys/module/rcutree/parameters/rcu_fanout_leaf

I made some changes to my device tree, and this is the output I get from

dmesg | grep -i fan
[    0.000000] 	Build-time adjustment of leaf fanout to 64.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=6
[    0.344254] vdd-fan: 5000 mV 
[    2.551996] thermal thermal_zone8: Registering thermal zone thermal_zone8 for type thermal-fan-est
[    3.127611] FAN dev name: pwm-fan
[    3.130981] Fan gpio: 398
[    3.133621] FAN:gpio request success.
<b>[    3.137293] FAN: can't find tach_gpio</b>
[    3.140982] pwm_fan_driver pwm-fan: cap state:7, cap pwm:255
[    3.146794] pwm_fan_driver pwm-fan: unable to request PWM, trying legacy API
[    3.501419] FAN dev name: pwm-fan
[    3.501441] Fan gpio: 398
[    3.501444] FAN:gpio request failed
[    3.501449] pwm_fan_driver: probe of pwm-fan failed with error -22
[    3.579397] vdd-fan: disabling

I was able to solve my earlier error of gpio request failed, but now it looks like the driver code fails when trying to find a ‘tach-gpio’. I can’t find a file in the sources, where this is actually defined, so I don’t know how it is able to find this in the dev kit as well.

Turns out, the pwm_id in my device tree was alsowrong. Not sure why though.
In my device tree, it was:

pwm_id = <4>;

When I changed it back to

pwm_id = <3>;

it works

I also changed this part in my device tree

vdd_fan: regulator@13 {
			compatible = "regulator-fixed-sync";
			reg = <13>;
			regulator-name = "vdd-fan";
			regulator-min-microvolt = <5000000>;
			regulator-max-microvolt = <5000000>;
			gpio = <TEGRA_MAIN_GPIO(J, 6) 0>;
		};

for the Auvidea J90 carrier
Now, I am able to control it. Thank you for the help

We are also facing same issue of GPIO request failed. May we know what changes you made in device tree in order to mitigate with this issue. We removed I2C used for fan disable and instead of that we configured GPIO to OFF the fan.

With above changes, tegra_fan node we are not getting in sys/kernel/debug/

We want to OFF the fan using GPIO and not through the I2C, so we configured GPIO to OFF the fan. But we are getting GPIO request failed error but we got vdd-fan GPIO access when we run cat /sys/kernel/debug/gpio. What else code changes needs to be done other than this.

Hi Namdevrj,

Is this still an issue on our side? If Yes, please help to raise a new topic with clear SW and HW information then we can start supporting from there.

Thanks