* [RFC PATCH 1/3] dt-bindings: mfd: rk808: add board level power hold GPIOs
2026-09-09 9:27 [RFC PATCH 0/3] Fix poweroff restarting the board on Firefly-RK3399 Yaozhong Li
@ 2026-09-09 9:27 ` Yaozhong Li
2026-09-09 9:27 ` [RFC PATCH 2/3] mfd: rk8xx: release the power hold GPIOs before powering off Yaozhong Li
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yaozhong Li @ 2026-09-09 9:27 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner, Chris Zhong, Zhang Qing
Cc: mfd, devicetree, linux-rockchip, linux-arm-kernel, linux-kernel,
Yaozhong Li
Some boards route "power hold" lines from the SoC into the board's power
circuitry. Those lines have to be held asserted while the system is
running and released before the PMIC shutdown request is written; with any
of them left asserted the rails drop and then come back up.
Add power-hold-gpios to describe those lines and power-hold-delay-ms for
the settle time.
Signed-off-by: Yaozhong Li <yaozhonguwl@gmail.com>
---
.../bindings/mfd/rockchip,rk808.yaml | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
index 50dfffa..00cbb27 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
@@ -43,6 +43,23 @@ properties:
system-power-controller: true
+ power-hold-gpios:
+ minItems: 1
+ maxItems: 2
+ description:
+ Board level power hold lines driven by the SoC. They have to be held
+ asserted while the system is running and released before the PMIC
+ shutdown request is written; with any of them left asserted the rails
+ drop and then come back up. A line left asserted by another consumer
+ therefore defeats the sequence, so every line involved must be listed
+ here.
+
+ power-hold-delay-ms:
+ default: 0
+ description:
+ Time to wait after releasing power-hold-gpios before the shutdown
+ request is written, to let the lines settle.
+
wakeup-source:
type: boolean
description:
@@ -113,6 +130,9 @@ properties:
unevaluatedProperties: false
unevaluatedProperties: false
+dependencies:
+ power-hold-delay-ms: [ power-hold-gpios ]
+
required:
- compatible
- reg
--
2.55.0.windows.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [RFC PATCH 2/3] mfd: rk8xx: release the power hold GPIOs before powering off
2026-09-09 9:27 [RFC PATCH 0/3] Fix poweroff restarting the board on Firefly-RK3399 Yaozhong Li
2026-09-09 9:27 ` [RFC PATCH 1/3] dt-bindings: mfd: rk808: add board level power hold GPIOs Yaozhong Li
@ 2026-09-09 9:27 ` Yaozhong Li
2026-09-09 9:27 ` [RFC PATCH 3/3] arm64: dts: rockchip: fix power-off on Firefly-RK3399 Yaozhong Li
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yaozhong Li @ 2026-09-09 9:27 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner, Chris Zhong, Zhang Qing
Cc: mfd, devicetree, linux-rockchip, linux-arm-kernel, linux-kernel,
Yaozhong Li
rk808_power_off() writes the PMIC's shutdown bit directly. On boards with
"power hold" lines driven by the SoC, a shutdown performed this way does
not stick: the rails drop and immediately come back up, so the board
restarts instead of staying off. U-Boot reports the result as a power-on
reset.
Take those lines as an optional GPIO array, hold them asserted while the
system runs and release them - waiting power-hold-delay-ms - before
writing the shutdown bit. Device trees without the property retain the
existing behaviour.
Releasing every described line matters: on a Firefly-RK3399 the board
stays off when both lines described for it are released, whereas releasing
GPIO1_D0 while GPIO1_B5 is left asserted makes it come back up.
Signed-off-by: Yaozhong Li <yaozhonguwl@gmail.com>
---
drivers/mfd/rk8xx-core.c | 29 +++++++++++++++++++++++++++++
include/linux/mfd/rk808.h | 4 ++++
2 files changed, 33 insertions(+)
diff --git a/drivers/mfd/rk8xx-core.c b/drivers/mfd/rk8xx-core.c
index 3dcf6ab..fd1efbb 100644
--- a/drivers/mfd/rk8xx-core.c
+++ b/drivers/mfd/rk8xx-core.c
@@ -11,6 +11,8 @@
*/
#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/mfd/rk808.h>
#include <linux/mfd/core.h>
@@ -703,6 +705,24 @@ static int rk808_power_off(struct sys_off_data *data)
default:
return NOTIFY_DONE;
}
+
+ /*
+ * Some boards route "power hold" lines from the SoC into the board's
+ * power circuitry. They have to be held asserted while the system is
+ * running and released before the PMIC shutdown request is written:
+ * with any of them left asserted, the rails drop and then come back
+ * up. Releasing them here rather than from a separate handler keeps
+ * the ordering against the I2C write explicit.
+ */
+ if (rk808->power_hold_gpios) {
+ unsigned int i;
+
+ for (i = 0; i < rk808->power_hold_gpios->ndescs; i++)
+ gpiod_set_value_cansleep(rk808->power_hold_gpios->desc[i], 0);
+
+ msleep(rk808->power_hold_delay_ms);
+ }
+
ret = regmap_update_bits(rk808->regmap, reg, bit, bit);
if (ret)
dev_err(rk808->dev, "Failed to shutdown device!\n");
@@ -874,6 +894,15 @@ int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap
if (device_property_read_bool(dev, "system-power-controller") ||
device_property_read_bool(dev, "rockchip,system-power-controller")) {
+ rk808->power_hold_gpios = devm_gpiod_get_array_optional(dev,
+ "power-hold", GPIOD_OUT_HIGH);
+ if (IS_ERR(rk808->power_hold_gpios))
+ return dev_err_probe(dev, PTR_ERR(rk808->power_hold_gpios),
+ "failed to get power hold GPIOs\n");
+
+ device_property_read_u32(dev, "power-hold-delay-ms",
+ &rk808->power_hold_delay_ms);
+
ret = devm_register_sys_off_handler(dev,
SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH,
&rk808_power_off, rk808);
diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
index 7ffc904..eda111e 100644
--- a/include/linux/mfd/rk808.h
+++ b/include/linux/mfd/rk808.h
@@ -1459,6 +1459,8 @@ enum {
RK818_ID = 0x8180,
};
+struct gpio_descs;
+
struct rk808 {
struct device *dev;
struct regmap_irq_chip_data *irq_data;
@@ -1466,6 +1468,8 @@ struct rk808 {
long variant;
const struct regmap_config *regmap_cfg;
const struct regmap_irq_chip *regmap_irq_chip;
+ struct gpio_descs *power_hold_gpios;
+ u32 power_hold_delay_ms;
};
void rk8xx_shutdown(struct device *dev);
--
2.55.0.windows.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [RFC PATCH 3/3] arm64: dts: rockchip: fix power-off on Firefly-RK3399
2026-09-09 9:27 [RFC PATCH 0/3] Fix poweroff restarting the board on Firefly-RK3399 Yaozhong Li
2026-09-09 9:27 ` [RFC PATCH 1/3] dt-bindings: mfd: rk808: add board level power hold GPIOs Yaozhong Li
2026-09-09 9:27 ` [RFC PATCH 2/3] mfd: rk8xx: release the power hold GPIOs before powering off Yaozhong Li
@ 2026-09-09 9:27 ` Yaozhong Li
2026-09-19 12:29 ` [RFC PATCH v2 0/3] Fix poweroff restarting the board " Yaozhong Li
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yaozhong Li @ 2026-09-09 9:27 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner, Chris Zhong, Zhang Qing
Cc: mfd, devicetree, linux-rockchip, linux-arm-kernel, linux-kernel,
Yaozhong Li
poweroff on this board drops the rails and immediately brings them back
up, so it reboots instead of staying off and U-Boot reports a power-on
reset.
Firefly's BSP drives GPIO1_D0 and GPIO1_B5 low during shutdown, before
writing the RK808's shutdown bit. Mainline does not describe GPIO1_D0 at
all, and describes GPIO1_B5 as the backlight enable GPIO - the vendor's
own backlight node has no enable GPIO. Nothing therefore releases either
line at power-off, and while the backlight owns GPIO1_B5 it can hold it
asserted, which is enough to make the board come back up on its own.
Describe both lines in the PMIC node and drop the backlight enable-gpios,
with the settle time the vendor uses.
Fixes: 171582e00db1 ("arm64: dts: rockchip: add support for firefly-rk3399 board")
Signed-off-by: Yaozhong Li <yaozhonguwl@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3399-firefly.dts | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
index 0568dfa..75b75fe 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
@@ -27,7 +27,6 @@ chosen {
backlight: backlight {
compatible = "pwm-backlight";
- enable-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
pwms = <&pwm0 0 25000 0>;
brightness-levels = <
0 1 2 3 4 5 6 7
@@ -327,6 +326,9 @@ rk808: pmic@1b {
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
system-power-controller;
+ power-hold-gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>,
+ <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
+ power-hold-delay-ms = <200>;
wakeup-source;
vcc1-supply = <&vcc_sys>;
--
2.55.0.windows.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [RFC PATCH v2 0/3] Fix poweroff restarting the board on Firefly-RK3399
2026-09-09 9:27 [RFC PATCH 0/3] Fix poweroff restarting the board on Firefly-RK3399 Yaozhong Li
` (2 preceding siblings ...)
2026-09-09 9:27 ` [RFC PATCH 3/3] arm64: dts: rockchip: fix power-off on Firefly-RK3399 Yaozhong Li
@ 2026-09-19 12:29 ` Yaozhong Li
2026-09-19 12:29 ` [RFC PATCH v2 1/3] dt-bindings: mfd: rk808: add board level power hold GPIOs Yaozhong Li
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yaozhong Li @ 2026-09-19 12:29 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner, Chris Zhong, Zhang Qing
Cc: mfd, devicetree, linux-rockchip, linux-arm-kernel, linux-kernel,
Yaozhong Li
Still an RFC: the patched kernel has not been booted on hardware (see
Testing), and the open questions from v1 about placement and naming are
unanswered.
v1: https://lore.kernel.org/all/20260909092728.1859-1-yaozhonguwl@gmail.com/
Changes since v1, addressing the Sashiko review Lee Jones asked me to act on
--------------------------------------------------------------------------
* [Medium] "Acquiring 'power-hold' GPIOs after registering MFD child devices
can cause probe deferral thrashing."
Fixed, and the finding was correct. v1 claimed the array after
devm_mfd_add_devices(), so a -EPROBE_DEFER from the GPIO provider would
have unwound the regulators, RTC and clocks on every retry. v2 claims it
before devm_regmap_add_irq_chip(), i.e. before anything is registered on
the device: the property test is hoisted into a bool and reused for the
sys-off registration further down, which is otherwise unchanged. A comment
records why the acquisition has to stay there.
Worth noting that this is exactly the part v1 disclosed as untested - the
out-of-tree proxy used for the functional testing claims the GPIOs at
module load, so it never exercises the probe path at all.
* [Low] "The commit message description violates the MFD subsystem formatting
rules by using a lowercase letter."
Fixed: "mfd: rk8xx: Release ...". The dt-bindings and arm64 dts subjects
keep their own subsystems' lowercase convention.
* The binding now states that power-hold-gpios is only meaningful together
with system-power-controller, which is what the driver implements. This is
not expressed as a "dependencies" entry because the driver also accepts the
deprecated rockchip,system-power-controller, and a dependency on one
spelling would reject device trees using the other.
* checkpatch --strict alignment fix in the GPIO acquisition; no functional
change.
The problem
-----------
On the Firefly-RK3399, "poweroff" drops the rails and immediately brings
them back up, so the board reboots instead of staying off. U-Boot reports
the result as a power-on reset.
Firefly's BSP drives two SoC pins low during shutdown, before writing the
RK808's shutdown bit: GPIO1_D0 and GPIO1_B5. Mainline does not describe
GPIO1_D0 at all, and describes GPIO1_B5 as the backlight enable GPIO,
although the vendor's own backlight node has no enable GPIO. Nothing
therefore releases either line at power-off.
What was established on the board is the sequence, not what happens inside
the PMIC: the shutdown sticks only when GPIO1_D0 goes from high to low
during power-off prepare, with GPIO1_B5 low, and the shutdown bit written
after a settle delay. Leaving GPIO1_B5 asserted makes the board come back
up even when GPIO1_D0 is released correctly, which is why the backlight
cannot keep that pin.
Why not gpio-poweroff
---------------------
gpio-poweroff drives the line active, back to inactive, then active again,
waits timeout-ms and then WARN()s on the assumption that it is itself
performing the power off, and it registers at SYS_OFF_MODE_POWER_OFF. Here
the RK808 performs the power off from its own POWER_OFF_PREPARE handler,
the lines only have to be released and left released, and there are two of
them.
rk3188-bqedison2qc.dts does drive a pwr_hold pin from gpio-poweroff, which
works there because pulling that line low is by itself enough to cut the
power. That is not the case here - driving a line low at runtime, with no
PMIC access at all, left this board running for the 10 s it was observed.
Open questions (unchanged from v1)
----------------------------------
1. Does this belong in the PMIC driver at all, rather than a small separate
driver registering at POWER_OFF_PREPARE with a higher priority?
2. Should the property be rockchip,power-hold-gpios? The vendor DT calls
these pins pmic,stby-gpio and pmic,hold-gpio.
3. Should the DT also carry a pinctrl group for the pins, as the vendor does?
4. Dropping the backlight enable-gpios is required for the sequence to work,
but nobody here has the schematic to confirm that property was wrong to
begin with.
Testing
-------
Tested on a Firefly-RK3399 (4 GB, RK808), shutdown captured on the debug
UART at 1500000 8N1. A run counts as "stayed off" only if the console
produced nothing for 150 s and there was no ICMP reply and no USB gadget
afterwards.
The patched kernel has NOT been booted: CONFIG_MFD_RK8XX is built in on the
test system and a full kernel build does not fit on it. The series compiles
(aarch64, W=1, no warnings), checkpatch --strict is clean, dt_binding_check
passes, and dtbs_check reports only the pre-existing usb2phy diagnostics for
this board, reproduced unchanged on the unpatched tree.
The functional evidence comes from an out-of-tree module using the same
gpiod array consumer name, the same GPIOD_OUT_HIGH, the same per-descriptor
gpiod_set_value_cansleep() loop and the same msleep() as this series,
against a device tree carrying exactly these properties, registered at
POWER_OFF_PREPARE with SYS_OFF_PRIO_HIGH + 1. It does not exercise the probe
path, so the v2 reordering above is not covered by it.
Every run started from a cold boot with both pins at their reset state
(inputs, low), verified by reading the GPIO registers beforehand:
both lines, as in this series: 3 of 3 stayed off
GPIO1_D0 only, GPIO1_B5 left low: 3 of 3 stayed off
GPIO1_B5 only, GPIO1_D0 left low: 0 of 2 stayed off
GPIO1_D0 released, GPIO1_B5 left high: 0 of 2 stayed off
nothing driven (mainline today): restarts after about 2 s
On this particular board pwm-backlight does not bind, so GPIO1_B5 stays an
input and describing GPIO1_D0 alone was enough here. That is not true in
general, which is why both lines are described and the backlight property is
dropped.
The 200 ms is the value the vendor uses; the threshold was not characterised.
The msleep() was measured at 200 to 201 ms on the console timestamps.
This series was prepared with AI assistance (Claude); the analysis and
the measurements on the board were reviewed by the author.
Yaozhong Li (3):
dt-bindings: mfd: rk808: add board level power hold GPIOs
mfd: rk8xx: Release the power hold GPIOs before powering off
arm64: dts: rockchip: fix power-off on Firefly-RK3399
.../bindings/mfd/rockchip,rk808.yaml | 21 +++++++++
.../boot/dts/rockchip/rk3399-firefly.dts | 4 +-
drivers/mfd/rk8xx-core.c | 47 ++++++++++++++++++-
include/linux/mfd/rk808.h | 4 ++
4 files changed, 73 insertions(+), 3 deletions(-)
--
2.55.0.windows.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [RFC PATCH v2 1/3] dt-bindings: mfd: rk808: add board level power hold GPIOs
2026-09-09 9:27 [RFC PATCH 0/3] Fix poweroff restarting the board on Firefly-RK3399 Yaozhong Li
` (3 preceding siblings ...)
2026-09-19 12:29 ` [RFC PATCH v2 0/3] Fix poweroff restarting the board " Yaozhong Li
@ 2026-09-19 12:29 ` Yaozhong Li
2026-09-19 12:29 ` [RFC PATCH v2 2/3] mfd: rk8xx: Release the power hold GPIOs before powering off Yaozhong Li
2026-09-19 12:29 ` [RFC PATCH v2 3/3] arm64: dts: rockchip: fix power-off on Firefly-RK3399 Yaozhong Li
6 siblings, 0 replies; 8+ messages in thread
From: Yaozhong Li @ 2026-09-19 12:29 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner, Chris Zhong, Zhang Qing
Cc: mfd, devicetree, linux-rockchip, linux-arm-kernel, linux-kernel,
Yaozhong Li
Some boards route "power hold" lines from the SoC into the board's power
circuitry. Those lines have to be held asserted while the system is
running and released before the PMIC shutdown request is written; with any
of them left asserted the rails drop and then come back up.
Add power-hold-gpios to describe those lines and power-hold-delay-ms for
the settle time.
Signed-off-by: Yaozhong Li <yaozhonguwl@gmail.com>
---
.../bindings/mfd/rockchip,rk808.yaml | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
index 50dfffa..d59f6ba 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
@@ -43,6 +43,24 @@ properties:
system-power-controller: true
+ power-hold-gpios:
+ minItems: 1
+ maxItems: 2
+ description:
+ Board level power hold lines driven by the SoC. They have to be held
+ asserted while the system is running and released before the PMIC
+ shutdown request is written; with any of them left asserted the rails
+ drop and then come back up. A line left asserted by another consumer
+ therefore defeats the sequence, so every line involved must be listed
+ here. Only meaningful together with system-power-controller, as the
+ lines are released as part of the PMIC's power-off path.
+
+ power-hold-delay-ms:
+ default: 0
+ description:
+ Time to wait after releasing power-hold-gpios before the shutdown
+ request is written, to let the lines settle.
+
wakeup-source:
type: boolean
description:
@@ -113,6 +131,9 @@ properties:
unevaluatedProperties: false
unevaluatedProperties: false
+dependencies:
+ power-hold-delay-ms: [ power-hold-gpios ]
+
required:
- compatible
- reg
--
2.55.0.windows.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [RFC PATCH v2 2/3] mfd: rk8xx: Release the power hold GPIOs before powering off
2026-09-09 9:27 [RFC PATCH 0/3] Fix poweroff restarting the board on Firefly-RK3399 Yaozhong Li
` (4 preceding siblings ...)
2026-09-19 12:29 ` [RFC PATCH v2 1/3] dt-bindings: mfd: rk808: add board level power hold GPIOs Yaozhong Li
@ 2026-09-19 12:29 ` Yaozhong Li
2026-09-19 12:29 ` [RFC PATCH v2 3/3] arm64: dts: rockchip: fix power-off on Firefly-RK3399 Yaozhong Li
6 siblings, 0 replies; 8+ messages in thread
From: Yaozhong Li @ 2026-09-19 12:29 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner, Chris Zhong, Zhang Qing
Cc: mfd, devicetree, linux-rockchip, linux-arm-kernel, linux-kernel,
Yaozhong Li
rk808_power_off() writes the PMIC's shutdown bit directly. On boards where
lines driven by the SoC gate the PMIC's power-off path, a shutdown
performed this way does not stick: the rails drop and immediately come
back up, so the board restarts instead of staying off. U-Boot reports the
result as a power-on reset.
Take those lines as an optional GPIO array, hold them asserted while the
system runs and release them - waiting power-hold-delay-ms - before
writing the shutdown bit. Device trees without the property retain the
existing behaviour.
The array is claimed before any child device is registered, so that a
-EPROBE_DEFER from the GPIO provider does not tear down the regulators,
RTC and clocks that devm_mfd_add_devices() has already registered.
Releasing every described line matters: on a Firefly-RK3399 the board
stays off when both lines described for it are released, whereas releasing
GPIO1_D0 while GPIO1_B5 is left asserted makes it come back up.
Signed-off-by: Yaozhong Li <yaozhonguwl@gmail.com>
---
drivers/mfd/rk8xx-core.c | 47 +++++++++++++++++++++++++++++++++++++--
include/linux/mfd/rk808.h | 4 ++++
2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/rk8xx-core.c b/drivers/mfd/rk8xx-core.c
index 3dcf6ab..0898db0 100644
--- a/drivers/mfd/rk8xx-core.c
+++ b/drivers/mfd/rk8xx-core.c
@@ -11,6 +11,8 @@
*/
#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/mfd/rk808.h>
#include <linux/mfd/core.h>
@@ -703,6 +705,24 @@ static int rk808_power_off(struct sys_off_data *data)
default:
return NOTIFY_DONE;
}
+
+ /*
+ * Some boards route "power hold" lines from the SoC into the board's
+ * power circuitry. They have to be held asserted while the system is
+ * running and released before the PMIC shutdown request is written:
+ * with any of them left asserted, the rails drop and then come back
+ * up. Releasing them here rather than from a separate handler keeps
+ * the ordering against the I2C write explicit.
+ */
+ if (rk808->power_hold_gpios) {
+ unsigned int i;
+
+ for (i = 0; i < rk808->power_hold_gpios->ndescs; i++)
+ gpiod_set_value_cansleep(rk808->power_hold_gpios->desc[i], 0);
+
+ msleep(rk808->power_hold_delay_ms);
+ }
+
ret = regmap_update_bits(rk808->regmap, reg, bit, bit);
if (ret)
dev_err(rk808->dev, "Failed to shutdown device!\n");
@@ -766,6 +786,7 @@ int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap
struct rk808 *rk808;
const struct rk808_reg_data *pre_init_reg;
const struct mfd_cell *cells;
+ bool system_power_controller;
int dual_support = 0;
int nr_pre_init_regs;
u32 rst_fun = 0;
@@ -851,6 +872,29 @@ int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap
if (!irq)
return dev_err_probe(dev, -EINVAL, "No interrupt support, no core IRQ\n");
+ system_power_controller =
+ device_property_read_bool(dev, "system-power-controller") ||
+ device_property_read_bool(dev, "rockchip,system-power-controller");
+
+ /*
+ * Claim the optional power hold GPIOs before any child device is
+ * registered. A -EPROBE_DEFER from the GPIO provider at this point
+ * costs nothing, whereas deferring after devm_mfd_add_devices()
+ * would tear the freshly registered children down again on every
+ * retry.
+ */
+ if (system_power_controller) {
+ rk808->power_hold_gpios =
+ devm_gpiod_get_array_optional(dev, "power-hold",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(rk808->power_hold_gpios))
+ return dev_err_probe(dev, PTR_ERR(rk808->power_hold_gpios),
+ "Failed to get power hold GPIOs\n");
+
+ device_property_read_u32(dev, "power-hold-delay-ms",
+ &rk808->power_hold_delay_ms);
+ }
+
ret = devm_regmap_add_irq_chip(dev, rk808->regmap, irq,
IRQF_ONESHOT | dual_support, -1,
rk808->regmap_irq_chip, &rk808->irq_data);
@@ -872,8 +916,7 @@ int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap
if (ret)
return dev_err_probe(dev, ret, "failed to add MFD devices\n");
- if (device_property_read_bool(dev, "system-power-controller") ||
- device_property_read_bool(dev, "rockchip,system-power-controller")) {
+ if (system_power_controller) {
ret = devm_register_sys_off_handler(dev,
SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH,
&rk808_power_off, rk808);
diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
index 7ffc904..eda111e 100644
--- a/include/linux/mfd/rk808.h
+++ b/include/linux/mfd/rk808.h
@@ -1459,6 +1459,8 @@ enum {
RK818_ID = 0x8180,
};
+struct gpio_descs;
+
struct rk808 {
struct device *dev;
struct regmap_irq_chip_data *irq_data;
@@ -1466,6 +1468,8 @@ struct rk808 {
long variant;
const struct regmap_config *regmap_cfg;
const struct regmap_irq_chip *regmap_irq_chip;
+ struct gpio_descs *power_hold_gpios;
+ u32 power_hold_delay_ms;
};
void rk8xx_shutdown(struct device *dev);
--
2.55.0.windows.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [RFC PATCH v2 3/3] arm64: dts: rockchip: fix power-off on Firefly-RK3399
2026-09-09 9:27 [RFC PATCH 0/3] Fix poweroff restarting the board on Firefly-RK3399 Yaozhong Li
` (5 preceding siblings ...)
2026-09-19 12:29 ` [RFC PATCH v2 2/3] mfd: rk8xx: Release the power hold GPIOs before powering off Yaozhong Li
@ 2026-09-19 12:29 ` Yaozhong Li
6 siblings, 0 replies; 8+ messages in thread
From: Yaozhong Li @ 2026-09-19 12:29 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner, Chris Zhong, Zhang Qing
Cc: mfd, devicetree, linux-rockchip, linux-arm-kernel, linux-kernel,
Yaozhong Li
poweroff on this board drops the rails and immediately brings them back
up, so it reboots instead of staying off and U-Boot reports a power-on
reset.
Firefly's BSP drives GPIO1_D0 and GPIO1_B5 low during shutdown, before
writing the RK808's shutdown bit. Mainline does not describe GPIO1_D0 at
all, and describes GPIO1_B5 as the backlight enable GPIO - the vendor's
own backlight node has no enable GPIO. Nothing therefore releases either
line at power-off, and while the backlight owns GPIO1_B5 it can hold it
asserted, which is enough to make the board come back up on its own.
Describe both lines in the PMIC node and drop the backlight enable-gpios,
with the settle time the vendor uses.
Fixes: 171582e00db1 ("arm64: dts: rockchip: add support for firefly-rk3399 board")
Signed-off-by: Yaozhong Li <yaozhonguwl@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3399-firefly.dts | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
index 0568dfa..75b75fe 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
@@ -27,7 +27,6 @@ chosen {
backlight: backlight {
compatible = "pwm-backlight";
- enable-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
pwms = <&pwm0 0 25000 0>;
brightness-levels = <
0 1 2 3 4 5 6 7
@@ -327,6 +326,9 @@ rk808: pmic@1b {
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
system-power-controller;
+ power-hold-gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>,
+ <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
+ power-hold-delay-ms = <200>;
wakeup-source;
vcc1-supply = <&vcc_sys>;
--
2.55.0.windows.3
^ permalink raw reply [flat|nested] 8+ messages in thread