* [PATCH v4 1/3] dt-bindings: mfd: rk8xx: add board level power hold GPIOs
2026-10-20 14:01 [PATCH v4 0/3] Fix poweroff restarting the board on Firefly-RK3399 Yaozhong Li
@ 2026-10-20 14:01 ` Yaozhong Li
2026-10-20 14:01 ` [PATCH v4 2/3] mfd: rk8xx: Release the power hold GPIOs before powering off Yaozhong Li
2026-10-20 14:01 ` [PATCH v4 3/3] arm64: dts: rockchip: fix power-off on Firefly-RK3399 Yaozhong Li
2 siblings, 0 replies; 4+ messages in thread
From: Yaozhong Li @ 2026-10-20 14:01 UTC (permalink / raw)
To: Lee Jones
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
Chris Zhong, Zhang Qing, Joseph Chen, Sebastian Reichel, 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,
otherwise the rails can drop and come back up instead of staying off.
Add power-hold-gpios to describe those lines and power-hold-delay-ms for
the settle time. The driver reads them for every RK8xx variant that is
the system power controller, so add them to all seven RK8xx schemas.
The array is bounded at two entries. Firefly's vendor kernel handles
exactly two such lines, pmic,hold-gpio and pmic,stby-gpio, and its board
files use one or both of them, with an RK808 and with an RK818.
The lines are released from the PMIC's power-off path, so they are only
meaningful when the PMIC is the system power controller. Require that,
accepting whichever spellings of the property each schema allows.
Assisted-by: LLM
Signed-off-by: Yaozhong Li <yaozhonguwl@gmail.com>
---
.../bindings/mfd/rockchip,rk801.yaml | 23 +++++++++++++++
.../bindings/mfd/rockchip,rk805.yaml | 29 +++++++++++++++++++
.../bindings/mfd/rockchip,rk806.yaml | 23 +++++++++++++++
.../bindings/mfd/rockchip,rk808.yaml | 29 +++++++++++++++++++
.../bindings/mfd/rockchip,rk816.yaml | 23 +++++++++++++++
.../bindings/mfd/rockchip,rk817.yaml | 29 +++++++++++++++++++
.../bindings/mfd/rockchip,rk818.yaml | 29 +++++++++++++++++++
7 files changed, 185 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk801.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk801.yaml
index 7c71447..2f9554d 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk801.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk801.yaml
@@ -29,6 +29,25 @@ properties:
description:
Telling whether or not this PMIC is controlling the system power.
+ 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, otherwise the rails can drop and come
+ back up instead of staying off. Only meaningful when this PMIC is the
+ system power controller, as the lines are released as part of its
+ power-off path.
+ The lines are released in the order listed, and power-hold-delay-ms
+ elapses once, after the last of them.
+
+ 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:
@@ -71,6 +90,10 @@ properties:
unevaluatedProperties: false
additionalProperties: false
+dependencies:
+ power-hold-delay-ms: [ power-hold-gpios ]
+ power-hold-gpios: [ system-power-controller ]
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml
index da23915..1a11c98 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml
@@ -48,6 +48,26 @@ 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, otherwise the rails can drop and come
+ back up instead of staying off. Only meaningful when this PMIC is the
+ system power controller, through either system-power-controller or
+ the deprecated rockchip,system-power-controller, as the lines are
+ released as part of its power-off path.
+ The lines are released in the order listed, and power-hold-delay-ms
+ elapses once, after the last of them.
+
+ 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:
@@ -102,6 +122,15 @@ allOf:
clock-output-names:
maxItems: 2
+dependencies:
+ power-hold-delay-ms: [ power-hold-gpios ]
+
+dependentSchemas:
+ power-hold-gpios:
+ anyOf:
+ - required: [ system-power-controller ]
+ - required: [ 'rockchip,system-power-controller' ]
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml
index eb5bca3..3df5501 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml
@@ -31,6 +31,25 @@ 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, otherwise the rails can drop and come
+ back up instead of staying off. Only meaningful when this PMIC is the
+ system power controller, as the lines are released as part of its
+ power-off path.
+ The lines are released in the order listed, and power-hold-delay-ms
+ elapses once, after the last of them.
+
+ 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.
+
rockchip,reset-mode:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2]
@@ -138,6 +157,10 @@ patternProperties:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml
+dependencies:
+ power-hold-delay-ms: [ power-hold-gpios ]
+ power-hold-gpios: [ system-power-controller ]
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
index 50dfffa..a331a2f 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml
@@ -43,6 +43,26 @@ 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, otherwise the rails can drop and come
+ back up instead of staying off. Only meaningful when this PMIC is the
+ system power controller, through either system-power-controller or
+ the deprecated rockchip,system-power-controller, as the lines are
+ released as part of its power-off path.
+ The lines are released in the order listed, and power-hold-delay-ms
+ elapses once, after the last of them.
+
+ 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 +133,15 @@ properties:
unevaluatedProperties: false
unevaluatedProperties: false
+dependencies:
+ power-hold-delay-ms: [ power-hold-gpios ]
+
+dependentSchemas:
+ power-hold-gpios:
+ anyOf:
+ - required: [ system-power-controller ]
+ - required: [ 'rockchip,system-power-controller' ]
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk816.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk816.yaml
index a58d945..f90e5d5 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk816.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk816.yaml
@@ -44,6 +44,25 @@ properties:
description:
Telling whether or not this PMIC is controlling the system power.
+ 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, otherwise the rails can drop and come
+ back up instead of staying off. Only meaningful when this PMIC is the
+ system power controller, as the lines are released as part of its
+ power-off path.
+ The lines are released in the order listed, and power-hold-delay-ms
+ elapses once, after the last of them.
+
+ 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: true
vcc1-supply:
@@ -101,6 +120,10 @@ patternProperties:
$ref: /schemas/types.yaml#/definitions/string
const: gpio0
+dependencies:
+ power-hold-delay-ms: [ power-hold-gpios ]
+ power-hold-gpios: [ system-power-controller ]
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml
index 2cb6d17..b1cc54e 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml
@@ -55,6 +55,26 @@ 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, otherwise the rails can drop and come
+ back up instead of staying off. Only meaningful when this PMIC is the
+ system power controller, through either system-power-controller or
+ the deprecated rockchip,system-power-controller, as the lines are
+ released as part of its power-off path.
+ The lines are released in the order listed, and power-hold-delay-ms
+ elapses once, after the last of them.
+
+ 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:
@@ -189,6 +209,15 @@ allOf:
patternProperties:
"^(BOOST|OTG_SWITCH)$": false
+dependencies:
+ power-hold-delay-ms: [ power-hold-gpios ]
+
+dependentSchemas:
+ power-hold-gpios:
+ anyOf:
+ - required: [ system-power-controller ]
+ - required: [ 'rockchip,system-power-controller' ]
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml
index 90d944c..96ec07a 100644
--- a/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml
+++ b/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml
@@ -43,6 +43,26 @@ 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, otherwise the rails can drop and come
+ back up instead of staying off. Only meaningful when this PMIC is the
+ system power controller, through either system-power-controller or
+ the deprecated rockchip,system-power-controller, as the lines are
+ released as part of its power-off path.
+ The lines are released in the order listed, and power-hold-delay-ms
+ elapses once, after the last of them.
+
+ 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:
@@ -105,6 +125,15 @@ properties:
unevaluatedProperties: false
unevaluatedProperties: false
+dependencies:
+ power-hold-delay-ms: [ power-hold-gpios ]
+
+dependentSchemas:
+ power-hold-gpios:
+ anyOf:
+ - required: [ system-power-controller ]
+ - required: [ 'rockchip,system-power-controller' ]
+
required:
- compatible
- reg
--
2.55.0.windows.3
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v4 2/3] mfd: rk8xx: Release the power hold GPIOs before powering off
2026-10-20 14:01 [PATCH v4 0/3] Fix poweroff restarting the board on Firefly-RK3399 Yaozhong Li
2026-10-20 14:01 ` [PATCH v4 1/3] dt-bindings: mfd: rk8xx: add board level power hold GPIOs Yaozhong Li
@ 2026-10-20 14:01 ` Yaozhong Li
2026-10-20 14:01 ` [PATCH v4 3/3] arm64: dts: rockchip: fix power-off on Firefly-RK3399 Yaozhong Li
2 siblings, 0 replies; 4+ messages in thread
From: Yaozhong Li @ 2026-10-20 14:01 UTC (permalink / raw)
To: Lee Jones
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
Chris Zhong, Zhang Qing, Joseph Chen, Sebastian Reichel, 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.
On a Firefly-RK3399 the shutdown stuck when such a line went from high to
low before the shutdown bit was written, and did not when the line was
never driven.
Assisted-by: LLM
Signed-off-by: Yaozhong Li <yaozhonguwl@gmail.com>
---
drivers/mfd/rk8xx-core.c | 49 +++++++++++++++++++++++++++++++++++++--
include/linux/mfd/rk808.h | 3 +++
2 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/rk8xx-core.c b/drivers/mfd/rk8xx-core.c
index 3dcf6ab..137ab20 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,22 @@ 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,
+ * otherwise the rails can drop and come back up instead of staying
+ * off. Releasing them here rather than from a separate handler keeps
+ * the ordering against the I2C write explicit.
+ */
+ if (rk808->power_hold_gpios) {
+ for (unsigned int line = 0; line < rk808->power_hold_gpios->ndescs; line++)
+ gpiod_set_value_cansleep(rk808->power_hold_gpios->desc[line], 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 +784,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 +870,33 @@ 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");
+
+ /*
+ * The settle time is optional. rk808 is zero initialised and
+ * the binding documents 0 as the default, so an absent property
+ * means the shutdown request follows the release with no wait.
+ */
+ 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 +918,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..e56d595 100644
--- a/include/linux/mfd/rk808.h
+++ b/include/linux/mfd/rk808.h
@@ -15,6 +15,7 @@
#ifndef __LINUX_REGULATOR_RK808_H
#define __LINUX_REGULATOR_RK808_H
+#include <linux/gpio/consumer.h>
#include <linux/regulator/machine.h>
#include <linux/regmap.h>
@@ -1466,6 +1467,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
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 4+ messages in thread