GPIO poweroff in Linux?

I’m currently playing around with DietPi, which is based on Debian Bullseye and uses the mainline kernel build from Armbian (5.10.123). dmesg output tells me this, which is encouraging:

[ 0.000000] psci: probing for conduit method from DT.
[ 0.000000] psci: PSCIv1.0 detected in firmware.
[ 0.000000] psci: Using standard PSCI v0.2 function IDs
[ 0.000000] psci: MIGRATE_INFO_TYPE not supported.
[ 0.000000] psci: SMC Calling Convention v1.1

But I just don’t know enough about this subject to know what, if anything, I can do to have the firmware pull a specified GPIO pin low on SYSTEM_OFF through PSCI.

1 Like

You can use this as an example, and fill gpio-poweroff part in the similar looking section. You will need to keep the GPIO pin definition in the same style as meson-g12a-w1-gpioao-3.dts.
Then you need to compile this dts file into dtbo object, and the easier way is to compile it in the kernel source tree.

I am also interested in gpio-poweroff for a safe shutdown. I am using the Ubuntu 20.04 image. Much less experience than either of you. I notice when running “gpioinfo” that line 82 already seems to functioning as a shutdown pin. Is this accessible anywhere on the board? Can this also be mapped to a pin on the header?

I’ve had a chance to read through all your posts and try out everything you’ve done. I can get the shutdown signal by commenting out the psci.c line like you did.

The way I see it there are two ways to solve this problem. A custom one-time solution or trying to make something that everyone in the community can use.

In terms on custom one-time solutions, what you have shared works. It takes a little time but it works and I consider it to be valid. As long as you can guarantee the GPIO will cut power as PSCI won’t be there to do it.

If this were to be solved perfectly for the community, there probably should be some code in the TF-A to assert the GPIO pin but still use PSCI if the power is not cut. The problem with this is that we would need to define some way to disable the GPIO so that this product can still be used by everybody.

The other community solution would be to find some way to get gpio-poweroff and psci to work together, but I feel this is out of scope considering the widespread use of both of these drivers.

Either way this solution works for now. Only way we could help the community more is by sharing our repos with the modified kernel and building dt overlays to make it configurable.

What do you think?

I agree. I think I found how Hardkernel implements this in this series of patches:



Maybe this could be adapted.

1 Like

I’m also (super slowly) trying to make one of these, and wanna do similar.

If it helps I made some power discoveries on the pins here. Plus you can push ethernet through the OTG at about 500MB I think.

I think I asked some questions on the MEGAPI github page about their on/off switch (which is what I was using to power this) or maybe I didn’t … either way, I had a really nice little box there which could make a great cheap TV box, if I could do safe shut-down and control that horrific fan.

Also, have you tried anyuthing with libmraa, @theophile?

At the moment, I have a functioning battery powered setup using the RetroPSU board, a 5000mAh battery, and a simple-but-effective safe shutdown circuit consisting of two resistors, three diodes, and a SPDT slide switch. The hardware was repurposed from my original build that used the Raspberry Pi Zero W.

The SBC connections are made directly to the GPIO pins. I’ve tested a 4-port USB2 hub connected to the “middle” port and it has had no trouble powering a 5" LCD display, a USB gamepad, a keyboard, and USB flash drive.

I haven’t done anything with libmraa yet. I played around with Armbian at first but I prefer the “just works” approach (and QOL enhancements) of Batocera. That system uses squashfs for the root filesystem. While it can be modified, it’s more involved than with a normal Linux distro, so I’m trying to do as much as possible through the the device tree.

1 Like

You see, you say:

But I see:

:sweat_smile:

((( thanks, though, I will try to learn french so that I can catch up with all this :wink: )))

No, I would definitely not use jangablards in a circuit like this. Too much potential for quantum displacement, which could result in accidental interdimensional travel.

You can buy a safe shutdown module here: https://www.humblebazooka.com/product/raspberry-pi-safe-shutdown-board-for-helders-retropsu/
If you go this route, you should probably get the version for the Adafruit PowerBoost 1000c because I think some resellers still have the Adafruit board in inventory. The RetroPSU appears to be out of stock for the foreseeable future.

I have patches that make the safe shutdown work on the Radxa Zero but I haven’t published them anywhere yet because they’re very hacky.

1 Like

BTW where did you get the 4.9 kernel for Zero? I’m actually trying to get Amlogic 4.9 kernel working on Zero 2 (mainline is missing CSI/DSI/NPU support) and currently can’t get it to boot.

It was the EmuELEC kernel. I’ve since got these patches working on mainline.

I gave TF-A bl31 a try today and I could boot into U-Boot’s hush shell. No further Linux boot was tested. I’m not sure if there is any practical benefit though.

Thanks, that’s good to know. Incidentally, from my further adventures with U-Boot, it appears that PSCI is supported in the standard vendor firmware packages, it’s just a matter of Linux driver implementation. From what I can gather, the Linux kernel only allows one pm_power_off handler to be registered. The PSCI driver and the gpio-poweroff driver both try to register a pm_power_off handler, but PSCI usually registers it first, causing gpio-poweroff driver loading to fail.

My hacky solution that is working for me is to manually edit psci.c to remove the line that registers the pm_power_off handler so that the gpio-poweroff driver can register it. The better solution is to either patch gpio-poweroff or write an alternate driver that does not attempt to register the pm_power_off handler at all, but instead initiates a system off command via PSCI.

Per the patches above, I think Hardkernel has implemented the latter via a new driver called odroid-reboot. It adds a Kconfig entry that suggests it should work on meson g12a SoCs, but I haven’t yet experimented with it on the Radxa Zero. If/when I do, I’ll report my experiences in this thread. In the meantime, if anyone else has any comments on the subject, they’d be much appreciated.

Also of possible interest, it looks like Raspberry Pi’s solution to this problem was to modify the gpio-poweroff driver to force registration of the pm_power_off handler overriding the PSCI registration, but in such a way that the PSCI handler will be restored if the gpio-poweroff module is unloaded or if the gpio device doesn’t remove power after a specified timeout:

This is probably not the perfect solution, but it’s way better than my “comment it out” approach. I’ll give this a shot and report back.

The RPi patches apply cleanly to 5.10 and work perfectly. The gpio-poweroff driver works as expected without having to disable the PSCI pm_power_off() handler. Normal shutdown and poweroff procedure appears to work normally as well so there does not appear to be a downside. I’ll plan to submit a PR for this so others can take advantage of it.

2 Likes

The change is merged. @Stephen will upload prebuilt kernel shortly.

Following @RadxaYuntian’s advices, I come up with the following overlay :

/dts-v1/;
/plugin/;

/ {
	compatible = "radxa,zero", "amlogic,g12a";

	fragment@0 {
		target-path = "/";
		__overlay__ {
			gpio-poweroff {
				compatible = "gpio-poweroff";
				/* gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; */
				gpios = <&gpio_ao 3 1>;
				status = "okay";
			};
		};
	};
};

I’ve removed the includes from w1-gpioao-3.dts, giving the raw pin number as found in the included file, so that it’s easier to compile.

The overlay compiles and loads successfully. From the latest @theophile’s comments, I believe it should perform as intended. I cannot confirm sin ce I can’t monitor the voltage on GPIOAO_3 (physical pin 7). I’ll report here if I get updates on this. Anyone able to test this overlay before me would be welcome to tell !

The sample overlay is already merged: https://github.com/radxa/kernel/commit/8989d6dd5cbb47e3a0dcb49abe0c9299051e798f#diff-f46cbf8dc1d5be28611a9274ede3f9324e3207af63c9b61533146cfbeef9612c

1 Like

How would one adapt this to work with a Rock Pi E or similar rk3328 based device?

My current failed attempt is this:

/dts-v1/;
/plugin/;

/ {
	compatible = "rockchip,rk3328";

	fragment@0 {
		target-path = "/";
		__overlay__ {
			gpio-poweroff {
				compatible = "gpio-poweroff";
				gpios = <&gpio1 24 0>;
				timeout-ms = <20000>;
				force;
			};
		};
	};
};

dtc -I dts -O dtb -f rk3328-poweroff-gpio1-24.dts -o /boot/dtb/rockchip/overlay/rk3328-poweroff-gpio1-24.dtbo

/boot/armbianEnv.txt:
overlays=rk3328-poweroff-gpio1-24

No output on gpio24 on shutdown complete.

Couple things. First, the overlay isn’t enough. You also need a kernel that has CONFIG_POWER_RESET_GPIO enabled, and depending on what kernel you’re using, you may need to either modify /drivers/firmware/psci/psci.c to comment out the ‘pm_power_off = psci_sys_poweroff’ line, or adapt these patches.

Second, it might be worth checking to see if the rk3328 can run a Hardkernel odroid kernel, as Hardkernel has a similar implementation of this already built in. I think the odroid go has an rk3326. I’m not sure how similar they are so maybe this is a non-starter, but probably worth a look just in case.

1 Like