* [PATCH 1/3] regulator: core: use system_freezable_wq for init complete work
2026-07-16 3:50 [PATCH 0/3] regulator: handle regulator late cleanup race with PM suspend Joy Zou
@ 2026-07-16 3:50 ` Joy Zou
2026-07-16 14:27 ` Frank Li
2026-07-16 3:50 ` [PATCH 2/3] regulator: pfuze100: add set_suspend_disable for LDO ops Joy Zou
2026-07-16 3:50 ` [PATCH 3/3] arm64: dts: imx8mq-evk: add regulator-off-in-suspend for VGEN1/VGEN6 Joy Zou
2 siblings, 1 reply; 7+ messages in thread
From: Joy Zou @ 2026-07-16 3:50 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Ye Li, Jacky Bai, Peng Fan, Dong Aisheng
Cc: linux-kernel, devicetree, imx, linux-arm-kernel, Joy Zou
schedule_delayed_work() uses system_wq, which is non-freezable, allowing
regulator_init_complete_work to run concurrently with system suspend. This
work fires ~30s after boot to disable unused regulators via I2C. When it
races with PM suspend, the I2C adapter may already be suspended, triggering
a -ESHUTDOWN warning dump.
[ 33.707233] pc : __i2c_transfer+0x36c/0x3c8
[ 33.707240] lr : __i2c_transfer+0x36c/0x3c8
[ 33.707246] sp : ffff80008239ba50
[ 33.707249] x29: ffff80008239ba50 x28: 0000000000000001 x27: 0000000000000000
[ 33.707259] x26: 0000000000000000 x25: 0000000000000001 x24: ffff0000c025c0e0
[ 33.707268] x23: 0000000000000000 x22: ffff0000c025c0e1 x21: 0000000000000001
[ 33.707277] x20: ffff80008239bae8 x19: ffff0000c0f54880 x18: fffffffffffeb320
[ 33.707287] x17: 000000040044ffff x16: 0000000000000000 x15: ffff800082086fd8
[ 33.707296] x14: 0000000000000000 x13: 0a6465646e657073 x12: 757320656c696877
[ 33.707305] x11: 0000000000000058 x10: 0000000000000018 x9 : ffff800082087060
[ 33.707314] x8 : 0000000000057fa8 x7 : 000000000000027d x6 : 0000000000000000
[ 33.707323] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 00000000ffffffff
[ 33.707333] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0000c0123480
[ 33.707343] Call trace:
[ 33.707346] __i2c_transfer+0x36c/0x3c8 (P)
[ 33.707356] i2c_transfer+0x6c/0xf8
[ 33.707364] i2c_transfer_buffer_flags+0x5c/0xa0
[ 33.707372] regmap_i2c_write+0x20/0x60
[ 33.707382] _regmap_raw_write_impl+0x5cc/0x660
[ 33.707389] _regmap_bus_raw_write+0x60/0x80
[ 33.707396] _regmap_write+0x58/0xc0
[ 33.707403] _regmap_update_bits+0x11c/0x140
[ 33.707409] regmap_update_bits_base+0x54/0x80
[ 33.707416] regulator_disable_regmap+0x40/0x5c
[ 33.707424] _regulator_do_disable+0x94/0xbc
[ 33.707435] CPU2 is up
[ 33.707433] regulator_late_cleanup+0xe0/0x1e8
[ 33.707442] class_for_each_device+0x104/0x13c
[ 33.707450] regulator_init_complete_work_function+0x54/0x80
[ 33.707458] process_one_work+0x150/0x290
[ 33.707467] worker_thread+0x180/0x2f4
[ 33.707473] kthread+0x12c/0x204
[ 33.707484] ret_from_fork+0x10/0x20
[ 33.707493] ---[ end trace 0000000000000000 ]---
Switch to system_freezable_wq so the work is frozen before any device
is suspended, eliminating the race.
Fixes: 55576cf18537 ("regulator: Defer init completion for a while after late_initcall")
Signed-off-by: Joy Zou <joy.zou@oss.nxp.com>
---
drivers/regulator/core.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 1797929dfe56..d5d24a940f31 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -27,6 +27,7 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/module.h>
+#include <linux/workqueue.h>
#define CREATE_TRACE_POINTS
#include <trace/events/regulator.h>
@@ -6882,8 +6883,9 @@ static int __init regulator_init_complete(void)
* we'd only do this on systems that need it, and a kernel
* command line option might be useful.
*/
- schedule_delayed_work(®ulator_init_complete_work,
- msecs_to_jiffies(30000));
+ queue_delayed_work(system_freezable_wq,
+ ®ulator_init_complete_work,
+ msecs_to_jiffies(30000));
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 1/3] regulator: core: use system_freezable_wq for init complete work
2026-07-16 3:50 ` [PATCH 1/3] regulator: core: use system_freezable_wq for init complete work Joy Zou
@ 2026-07-16 14:27 ` Frank Li
0 siblings, 0 replies; 7+ messages in thread
From: Frank Li @ 2026-07-16 14:27 UTC (permalink / raw)
To: Joy Zou
Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Ye Li, Jacky Bai, Peng Fan, Dong Aisheng,
linux-kernel, devicetree, imx, linux-arm-kernel
On Thu, Jul 16, 2026 at 11:50:53AM +0800, Joy Zou wrote:
> schedule_delayed_work() uses system_wq, which is non-freezable, allowing
> regulator_init_complete_work to run concurrently with system suspend. This
> work fires ~30s after boot to disable unused regulators via I2C. When it
> races with PM suspend, the I2C adapter may already be suspended, triggering
> a -ESHUTDOWN warning dump.
>
> [ 33.707233] pc : __i2c_transfer+0x36c/0x3c8
> [ 33.707240] lr : __i2c_transfer+0x36c/0x3c8
> [ 33.707246] sp : ffff80008239ba50
> [ 33.707249] x29: ffff80008239ba50 x28: 0000000000000001 x27: 0000000000000000
> [ 33.707259] x26: 0000000000000000 x25: 0000000000000001 x24: ffff0000c025c0e0
> [ 33.707268] x23: 0000000000000000 x22: ffff0000c025c0e1 x21: 0000000000000001
> [ 33.707277] x20: ffff80008239bae8 x19: ffff0000c0f54880 x18: fffffffffffeb320
> [ 33.707287] x17: 000000040044ffff x16: 0000000000000000 x15: ffff800082086fd8
> [ 33.707296] x14: 0000000000000000 x13: 0a6465646e657073 x12: 757320656c696877
> [ 33.707305] x11: 0000000000000058 x10: 0000000000000018 x9 : ffff800082087060
> [ 33.707314] x8 : 0000000000057fa8 x7 : 000000000000027d x6 : 0000000000000000
> [ 33.707323] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 00000000ffffffff
> [ 33.707333] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0000c0123480
> [ 33.707343] Call trace:
> [ 33.707346] __i2c_transfer+0x36c/0x3c8 (P)
> [ 33.707356] i2c_transfer+0x6c/0xf8
> [ 33.707364] i2c_transfer_buffer_flags+0x5c/0xa0
> [ 33.707372] regmap_i2c_write+0x20/0x60
> [ 33.707382] _regmap_raw_write_impl+0x5cc/0x660
> [ 33.707389] _regmap_bus_raw_write+0x60/0x80
> [ 33.707396] _regmap_write+0x58/0xc0
> [ 33.707403] _regmap_update_bits+0x11c/0x140
> [ 33.707409] regmap_update_bits_base+0x54/0x80
> [ 33.707416] regulator_disable_regmap+0x40/0x5c
> [ 33.707424] _regulator_do_disable+0x94/0xbc
> [ 33.707435] CPU2 is up
> [ 33.707433] regulator_late_cleanup+0xe0/0x1e8
> [ 33.707442] class_for_each_device+0x104/0x13c
> [ 33.707450] regulator_init_complete_work_function+0x54/0x80
> [ 33.707458] process_one_work+0x150/0x290
> [ 33.707467] worker_thread+0x180/0x2f4
> [ 33.707473] kthread+0x12c/0x204
> [ 33.707484] ret_from_fork+0x10/0x20
> [ 33.707493] ---[ end trace 0000000000000000 ]---
>
> Switch to system_freezable_wq so the work is frozen before any device
> is suspended, eliminating the race.
>
> Fixes: 55576cf18537 ("regulator: Defer init completion for a while after late_initcall")
> Signed-off-by: Joy Zou <joy.zou@oss.nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/regulator/core.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
> index 1797929dfe56..d5d24a940f31 100644
> --- a/drivers/regulator/core.c
> +++ b/drivers/regulator/core.c
> @@ -27,6 +27,7 @@
> #include <linux/regulator/driver.h>
> #include <linux/regulator/machine.h>
> #include <linux/module.h>
> +#include <linux/workqueue.h>
>
> #define CREATE_TRACE_POINTS
> #include <trace/events/regulator.h>
> @@ -6882,8 +6883,9 @@ static int __init regulator_init_complete(void)
> * we'd only do this on systems that need it, and a kernel
> * command line option might be useful.
> */
> - schedule_delayed_work(®ulator_init_complete_work,
> - msecs_to_jiffies(30000));
> + queue_delayed_work(system_freezable_wq,
> + ®ulator_init_complete_work,
> + msecs_to_jiffies(30000));
>
> return 0;
> }
>
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/3] regulator: pfuze100: add set_suspend_disable for LDO ops
2026-07-16 3:50 [PATCH 0/3] regulator: handle regulator late cleanup race with PM suspend Joy Zou
2026-07-16 3:50 ` [PATCH 1/3] regulator: core: use system_freezable_wq for init complete work Joy Zou
@ 2026-07-16 3:50 ` Joy Zou
2026-07-16 14:28 ` Frank Li
2026-07-16 3:50 ` [PATCH 3/3] arm64: dts: imx8mq-evk: add regulator-off-in-suspend for VGEN1/VGEN6 Joy Zou
2 siblings, 1 reply; 7+ messages in thread
From: Joy Zou @ 2026-07-16 3:50 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Ye Li, Jacky Bai, Peng Fan, Dong Aisheng
Cc: linux-kernel, devicetree, imx, linux-arm-kernel, Joy Zou
Add set_suspend_disable callback to pfuze100_ldo_regulator_ops to
support regulator-off-in-suspend DTS property for VGEN regulators.
This allows unused LDO regulators to be properly disabled during
system suspend, reducing power consumption.
Signed-off-by: Joy Zou <joy.zou@oss.nxp.com>
---
drivers/regulator/pfuze100-regulator.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
index 7d56c22b5e40..e6d3a28baadc 100644
--- a/drivers/regulator/pfuze100-regulator.c
+++ b/drivers/regulator/pfuze100-regulator.c
@@ -158,6 +158,22 @@ static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
return ret;
}
+static int pfuze100_set_suspend_disable(struct regulator_dev *rdev)
+{
+ struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+
+ /*
+ * Set VGENxSTBY and clear VGENxLPWR so that the LDO output is
+ * disabled when the PMIC receives a STANDBY event.
+ * EN=1, LPWR=0, STBY=1 results in output Off when STANDBY is asserted.
+ */
+ return regmap_update_bits(pfuze100->regmap,
+ pfuze100->regulator_descs[id].stby_reg,
+ PFUZE100_VGENxSTBY | PFUZE100_VGENxLPWR,
+ PFUZE100_VGENxSTBY);
+}
+
static const struct regulator_ops pfuze100_ldo_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -165,6 +181,7 @@ static const struct regulator_ops pfuze100_ldo_regulator_ops = {
.list_voltage = regulator_list_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_suspend_disable = pfuze100_set_suspend_disable,
};
static const struct regulator_ops pfuze100_fixed_regulator_ops = {
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 2/3] regulator: pfuze100: add set_suspend_disable for LDO ops
2026-07-16 3:50 ` [PATCH 2/3] regulator: pfuze100: add set_suspend_disable for LDO ops Joy Zou
@ 2026-07-16 14:28 ` Frank Li
0 siblings, 0 replies; 7+ messages in thread
From: Frank Li @ 2026-07-16 14:28 UTC (permalink / raw)
To: Joy Zou
Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Ye Li, Jacky Bai, Peng Fan, Dong Aisheng,
linux-kernel, devicetree, imx, linux-arm-kernel
On Thu, Jul 16, 2026 at 11:50:54AM +0800, Joy Zou wrote:
> Add set_suspend_disable callback to pfuze100_ldo_regulator_ops to
> support regulator-off-in-suspend DTS property for VGEN regulators.
> This allows unused LDO regulators to be properly disabled during
> system suspend, reducing power consumption.
>
> Signed-off-by: Joy Zou <joy.zou@oss.nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/regulator/pfuze100-regulator.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
> index 7d56c22b5e40..e6d3a28baadc 100644
> --- a/drivers/regulator/pfuze100-regulator.c
> +++ b/drivers/regulator/pfuze100-regulator.c
> @@ -158,6 +158,22 @@ static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
> return ret;
> }
>
> +static int pfuze100_set_suspend_disable(struct regulator_dev *rdev)
> +{
> + struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev);
> + int id = rdev_get_id(rdev);
> +
> + /*
> + * Set VGENxSTBY and clear VGENxLPWR so that the LDO output is
> + * disabled when the PMIC receives a STANDBY event.
> + * EN=1, LPWR=0, STBY=1 results in output Off when STANDBY is asserted.
> + */
> + return regmap_update_bits(pfuze100->regmap,
> + pfuze100->regulator_descs[id].stby_reg,
> + PFUZE100_VGENxSTBY | PFUZE100_VGENxLPWR,
> + PFUZE100_VGENxSTBY);
> +}
> +
> static const struct regulator_ops pfuze100_ldo_regulator_ops = {
> .enable = regulator_enable_regmap,
> .disable = regulator_disable_regmap,
> @@ -165,6 +181,7 @@ static const struct regulator_ops pfuze100_ldo_regulator_ops = {
> .list_voltage = regulator_list_voltage_linear,
> .set_voltage_sel = regulator_set_voltage_sel_regmap,
> .get_voltage_sel = regulator_get_voltage_sel_regmap,
> + .set_suspend_disable = pfuze100_set_suspend_disable,
> };
>
> static const struct regulator_ops pfuze100_fixed_regulator_ops = {
>
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/3] arm64: dts: imx8mq-evk: add regulator-off-in-suspend for VGEN1/VGEN6
2026-07-16 3:50 [PATCH 0/3] regulator: handle regulator late cleanup race with PM suspend Joy Zou
2026-07-16 3:50 ` [PATCH 1/3] regulator: core: use system_freezable_wq for init complete work Joy Zou
2026-07-16 3:50 ` [PATCH 2/3] regulator: pfuze100: add set_suspend_disable for LDO ops Joy Zou
@ 2026-07-16 3:50 ` Joy Zou
2026-07-16 14:31 ` Frank Li
2 siblings, 1 reply; 7+ messages in thread
From: Joy Zou @ 2026-07-16 3:50 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Ye Li, Jacky Bai, Peng Fan, Dong Aisheng
Cc: linux-kernel, devicetree, imx, linux-arm-kernel, Joy Zou
VGEN1 and VGEN6 have no consumers and are not always-on, causing the
regulator cleanup work to race with PM suspend. Mark them as
regulator-off-in-suspend to disable them properly during suspend and
reduce power consumption.
Signed-off-by: Joy Zou <joy.zou@oss.nxp.com>
---
arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
index 5ea04703ddd7..fc0303e44433 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
@@ -299,6 +299,9 @@ vref_reg: vrefddr {
vgen1_reg: vgen1 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1550000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
};
vgen2_reg: vgen2 {
@@ -328,6 +331,9 @@ vgen5_reg: vgen5 {
vgen6_reg: vgen6 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
};
};
};
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 3/3] arm64: dts: imx8mq-evk: add regulator-off-in-suspend for VGEN1/VGEN6
2026-07-16 3:50 ` [PATCH 3/3] arm64: dts: imx8mq-evk: add regulator-off-in-suspend for VGEN1/VGEN6 Joy Zou
@ 2026-07-16 14:31 ` Frank Li
0 siblings, 0 replies; 7+ messages in thread
From: Frank Li @ 2026-07-16 14:31 UTC (permalink / raw)
To: Joy Zou
Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Ye Li, Jacky Bai, Peng Fan, Dong Aisheng,
linux-kernel, devicetree, imx, linux-arm-kernel
On Thu, Jul 16, 2026 at 11:50:55AM +0800, Joy Zou wrote:
> VGEN1 and VGEN6 have no consumers and are not always-on, causing the
> regulator cleanup work to race with PM suspend.
why cause race? You first patch set workqueue to system_freezable_wq
Frank
> Mark them as
> regulator-off-in-suspend to disable them properly during suspend and
> reduce power consumption.
>
> Signed-off-by: Joy Zou <joy.zou@oss.nxp.com>
> ---
> arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
> index 5ea04703ddd7..fc0303e44433 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
> +++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
> @@ -299,6 +299,9 @@ vref_reg: vrefddr {
> vgen1_reg: vgen1 {
> regulator-min-microvolt = <800000>;
> regulator-max-microvolt = <1550000>;
> + regulator-state-mem {
> + regulator-off-in-suspend;
> + };
> };
>
> vgen2_reg: vgen2 {
> @@ -328,6 +331,9 @@ vgen5_reg: vgen5 {
> vgen6_reg: vgen6 {
> regulator-min-microvolt = <1800000>;
> regulator-max-microvolt = <3300000>;
> + regulator-state-mem {
> + regulator-off-in-suspend;
> + };
> };
> };
> };
>
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread