Add poweroff node to allow the board to power itself off after shutdown
by disabling the SYSTEM and CPUX regulators (U5 resp. U6). The RST
button can be used to restart the board.
Signed-off-by: Michael Klein <[email protected]>
---
arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
index 4c6704e4c57e..ea2fa48a1647 100644
--- a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
+++ b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
@@ -46,6 +46,11 @@ sw4 {
};
};
+ poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */
+ };
+
reg_vdd_cpux: vdd-cpux-regulator {
compatible = "regulator-gpio";
regulator-name = "vdd-cpux";
--
2.29.2
On Tue, Nov 24, 2020 at 02:36:33PM +0100, Michael Klein wrote:
> Add poweroff node to allow the board to power itself off after shutdown
> by disabling the SYSTEM and CPUX regulators (U5 resp. U6). The RST
> button can be used to restart the board.
>
> Signed-off-by: Michael Klein <[email protected]>
> ---
> arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts | 5 +++++
> 1 file changed, 5 insertions(+)
You should have a summary of the changes between versions here
> diff --git a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
> index 4c6704e4c57e..ea2fa48a1647 100644
> --- a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
> +++ b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
> @@ -46,6 +46,11 @@ sw4 {
> };
> };
>
> + poweroff {
> + compatible = "gpio-poweroff";
> + gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */
> + };
> +
Like I said in the previous version, this should really be modelled as a
regulator instead of just a GPIO
Maxime
On Tue, Nov 24, 2020 at 03:26:56PM +0100, Maxime Ripard wrote:
>On Tue, Nov 24, 2020 at 02:36:33PM +0100, Michael Klein wrote:
>> Add poweroff node to allow the board to power itself off after shutdown
>> by disabling the SYSTEM and CPUX regulators (U5 resp. U6). The RST
>> button can be used to restart the board.
>>
>> Signed-off-by: Michael Klein <[email protected]>
>> ---
>> arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts | 5 +++++
>> 1 file changed, 5 insertions(+)
>
>You should have a summary of the changes between versions here
>
>> diff --git a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
>> index 4c6704e4c57e..ea2fa48a1647 100644
>> --- a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
>> +++ b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
>> @@ -46,6 +46,11 @@ sw4 {
>> };
>> };
>>
>> + poweroff {
>> + compatible = "gpio-poweroff";
>> + gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */
>> + };
>> +
>
>Like I said in the previous version, this should really be modelled as a
>regulator instead of just a GPIO
Please excuse my ignorance, do you mean something like this?
reg_vdd_sys: vdd-sys {
compatible = "regulator-fixed";
regulator-name = "vdd-sys";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-always-on;
regulator-boot-on;
enable-active-high;
gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
vin-supply = <®_vcc5v0>;
};
With this, the board still draws 60mA (cheap USB ampere meter) after
shutdown, presumably because of "regulator-always-on". Without this
property the board powers off shortly after booting up.
Michael
On Tue, Nov 24, 2020 at 11:31:59PM +0100, Michael Klein wrote:
> On Tue, Nov 24, 2020 at 03:26:56PM +0100, Maxime Ripard wrote:
> > On Tue, Nov 24, 2020 at 02:36:33PM +0100, Michael Klein wrote:
> > > Add poweroff node to allow the board to power itself off after shutdown
> > > by disabling the SYSTEM and CPUX regulators (U5 resp. U6). The RST
> > > button can be used to restart the board.
> > >
> > > Signed-off-by: Michael Klein <[email protected]>
> > > ---
> > > arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts | 5 +++++
> > > 1 file changed, 5 insertions(+)
> >
> > You should have a summary of the changes between versions here
> >
> > > diff --git a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
> > > index 4c6704e4c57e..ea2fa48a1647 100644
> > > --- a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
> > > +++ b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
> > > @@ -46,6 +46,11 @@ sw4 {
> > > };
> > > };
> > >
> > > + poweroff {
> > > + compatible = "gpio-poweroff";
> > > + gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */
> > > + };
> > > +
> >
> > Like I said in the previous version, this should really be modelled as a
> > regulator instead of just a GPIO
>
> Please excuse my ignorance, do you mean something like this?
>
> reg_vdd_sys: vdd-sys {
> compatible = "regulator-fixed";
> regulator-name = "vdd-sys";
> regulator-min-microvolt = <1200000>;
> regulator-max-microvolt = <1200000>;
> regulator-always-on;
> regulator-boot-on;
> enable-active-high;
> gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
> vin-supply = <®_vcc5v0>;
> };
>
> With this, the board still draws 60mA (cheap USB ampere meter) after
> shutdown, presumably because of "regulator-always-on". Without this
> property the board powers off shortly after booting up.
Yes, because you're only describing the regulator itself here, but
you're not telling linux that it needs to shut it down to power-down the
board.
You'd need a driver similar to gpio-poweroff, using a regulator instead,
and calling regulator_force_disable to shut it down
Maxime
Changes in v2:
- rename DT node
Changes in v3:
- add regulator-poweroff driver
- use regulator-poweroff driver instead of gpio-poweroff
Michael Klein (3):
power: reset: new driver regulator-poweroff
Documentation: DT: binding documentation for regulator-poweroff
ARM: dts: sun8i-h2-plus-bananapi-m2-zero: add poweroff node
.../power/reset/regulator-poweroff.yaml | 53 +++++++++
.../dts/sun8i-h2-plus-bananapi-m2-zero.dts | 7 ++
drivers/power/reset/Kconfig | 7 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/regulator-poweroff.c | 107 ++++++++++++++++++
5 files changed, 175 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/reset/regulator-poweroff.yaml
create mode 100644 drivers/power/reset/regulator-poweroff.c
--
2.29.2
This driver registers a pm_power_off function to disable a set of
regulators defined in the devicetree to turn off the board.
Signed-off-by: Michael Klein <[email protected]>
---
drivers/power/reset/Kconfig | 7 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/regulator-poweroff.c | 107 +++++++++++++++++++++++
3 files changed, 115 insertions(+)
create mode 100644 drivers/power/reset/regulator-poweroff.c
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index d55b3727e00e..ae6cb7b0bd4d 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -177,6 +177,13 @@ config POWER_RESET_QNAP
Say Y if you have a QNAP NAS.
+config POWER_RESET_REGULATOR
+ bool "Regulator subsystem power-off driver"
+ depends on OF && REGULATOR
+ help
+ This driver supports turning off your board by disabling a set
+ of regulators defined in the devicetree.
+
config POWER_RESET_RESTART
bool "Restart power-off driver"
help
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index c51eceba9ea3..9dc49d3a57ff 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o
obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
+obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o
obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o
obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o
diff --git a/drivers/power/reset/regulator-poweroff.c b/drivers/power/reset/regulator-poweroff.c
new file mode 100644
index 000000000000..df2ca4fdcc49
--- /dev/null
+++ b/drivers/power/reset/regulator-poweroff.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Force-disables a regulator to power down a device
+ *
+ * Michael Klein <[email protected]>
+ *
+ * Copyright (C) 2020 Michael Klein
+ *
+ * Based on the gpio-poweroff driver.
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#define DEFAULT_TIMEOUT_MS 3000
+
+/*
+ * Hold configuration here, cannot be more than one instance of the driver
+ * since pm_power_off itself is global.
+ */
+static struct regulator **poweroff_regulators;
+static u32 timeout = DEFAULT_TIMEOUT_MS;
+
+static void regulator_poweroff_do_poweroff(void)
+{
+ struct regulator **it;
+
+ if (poweroff_regulators)
+ for (it = poweroff_regulators; *it; ++it)
+ if (regulator_is_enabled(*it))
+ regulator_force_disable(*it);
+
+ /* give it some time */
+ mdelay(timeout);
+
+ WARN_ON(1);
+}
+
+static int regulator_poweroff_probe(struct platform_device *pdev)
+{
+ int count;
+ const char *name;
+ struct regulator **it;
+ struct property *prop;
+ struct device_node *node = pdev->dev.of_node;
+
+ /* If a pm_power_off function has already been added, leave it alone */
+ if (pm_power_off != NULL) {
+ dev_err(&pdev->dev,
+ "%s: pm_power_off function already registered\n",
+ __func__);
+ return -EBUSY;
+ }
+
+ count = of_property_count_strings(node, "regulator-names");
+ if (count <= 0)
+ return -ENOENT;
+
+ poweroff_regulators = devm_kcalloc(&pdev->dev, count + 1,
+ sizeof(struct regulator *), GFP_KERNEL);
+
+ it = poweroff_regulators;
+ of_property_for_each_string(node, "regulator-names", prop, name) {
+ *it = devm_regulator_get(&pdev->dev, name);
+ if (IS_ERR(*it))
+ return PTR_ERR(*it);
+ it++;
+ }
+
+ of_property_read_u32(node, "timeout-ms", &timeout);
+
+ pm_power_off = ®ulator_poweroff_do_poweroff;
+ return 0;
+}
+
+static int regulator_poweroff_remove(__maybe_unused struct platform_device *pdev)
+{
+ if (pm_power_off == ®ulator_poweroff_do_poweroff)
+ pm_power_off = NULL;
+
+ return 0;
+}
+
+static const struct of_device_id of_regulator_poweroff_match[] = {
+ { .compatible = "regulator-poweroff", },
+ {},
+};
+
+static struct platform_driver regulator_poweroff_driver = {
+ .probe = regulator_poweroff_probe,
+ .remove = regulator_poweroff_remove,
+ .driver = {
+ .name = "poweroff-regulator",
+ .of_match_table = of_regulator_poweroff_match,
+ },
+};
+
+module_platform_driver(regulator_poweroff_driver);
+
+MODULE_AUTHOR("Michael Klein <[email protected]>");
+MODULE_DESCRIPTION("Regulator poweroff driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:poweroff-regulator");
--
2.29.2
On Mon, Dec 07, 2020 at 03:27:54PM +0100, Michael Klein wrote:
> This driver registers a pm_power_off function to disable a set of
> regulators defined in the devicetree to turn off the board.
>
> Signed-off-by: Michael Klein <[email protected]>
> ---
> drivers/power/reset/Kconfig | 7 ++
> drivers/power/reset/Makefile | 1 +
> drivers/power/reset/regulator-poweroff.c | 107 +++++++++++++++++++++++
> 3 files changed, 115 insertions(+)
> create mode 100644 drivers/power/reset/regulator-poweroff.c
>
> diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
> index d55b3727e00e..ae6cb7b0bd4d 100644
> --- a/drivers/power/reset/Kconfig
> +++ b/drivers/power/reset/Kconfig
> @@ -177,6 +177,13 @@ config POWER_RESET_QNAP
>
> Say Y if you have a QNAP NAS.
>
> +config POWER_RESET_REGULATOR
> + bool "Regulator subsystem power-off driver"
> + depends on OF && REGULATOR
> + help
> + This driver supports turning off your board by disabling a set
> + of regulators defined in the devicetree.
> +
> config POWER_RESET_RESTART
> bool "Restart power-off driver"
> help
> diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
> index c51eceba9ea3..9dc49d3a57ff 100644
> --- a/drivers/power/reset/Makefile
> +++ b/drivers/power/reset/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
> obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o
> obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
> obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
> +obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o
> obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
> obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o
> obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o
> diff --git a/drivers/power/reset/regulator-poweroff.c b/drivers/power/reset/regulator-poweroff.c
> new file mode 100644
> index 000000000000..df2ca4fdcc49
> --- /dev/null
> +++ b/drivers/power/reset/regulator-poweroff.c
> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Force-disables a regulator to power down a device
> + *
> + * Michael Klein <[email protected]>
> + *
> + * Copyright (C) 2020 Michael Klein
> + *
> + * Based on the gpio-poweroff driver.
> + */
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +#define DEFAULT_TIMEOUT_MS 3000
> +
> +/*
> + * Hold configuration here, cannot be more than one instance of the driver
> + * since pm_power_off itself is global.
> + */
> +static struct regulator **poweroff_regulators;
> +static u32 timeout = DEFAULT_TIMEOUT_MS;
> +
> +static void regulator_poweroff_do_poweroff(void)
> +{
> + struct regulator **it;
> +
> + if (poweroff_regulators)
> + for (it = poweroff_regulators; *it; ++it)
> + if (regulator_is_enabled(*it))
> + regulator_force_disable(*it);
> +
> + /* give it some time */
> + mdelay(timeout);
> +
> + WARN_ON(1);
> +}
> +
> +static int regulator_poweroff_probe(struct platform_device *pdev)
> +{
> + int count;
> + const char *name;
> + struct regulator **it;
> + struct property *prop;
> + struct device_node *node = pdev->dev.of_node;
> +
> + /* If a pm_power_off function has already been added, leave it alone */
> + if (pm_power_off != NULL) {
> + dev_err(&pdev->dev,
> + "%s: pm_power_off function already registered\n",
> + __func__);
> + return -EBUSY;
> + }
> +
> + count = of_property_count_strings(node, "regulator-names");
> + if (count <= 0)
> + return -ENOENT;
> +
> + poweroff_regulators = devm_kcalloc(&pdev->dev, count + 1,
> + sizeof(struct regulator *), GFP_KERNEL);
> +
> + it = poweroff_regulators;
> + of_property_for_each_string(node, "regulator-names", prop, name) {
> + *it = devm_regulator_get(&pdev->dev, name);
> + if (IS_ERR(*it))
> + return PTR_ERR(*it);
> + it++;
> + }
> +
> + of_property_read_u32(node, "timeout-ms", &timeout);
> +
> + pm_power_off = ®ulator_poweroff_do_poweroff;
> + return 0;
> +}
> +
> +static int regulator_poweroff_remove(__maybe_unused struct platform_device *pdev)
> +{
> + if (pm_power_off == ®ulator_poweroff_do_poweroff)
> + pm_power_off = NULL;
> +
> + return 0;
> +}
> +
> +static const struct of_device_id of_regulator_poweroff_match[] = {
> + { .compatible = "regulator-poweroff", },
> + {},
> +};
> +
> +static struct platform_driver regulator_poweroff_driver = {
> + .probe = regulator_poweroff_probe,
> + .remove = regulator_poweroff_remove,
> + .driver = {
> + .name = "poweroff-regulator",
> + .of_match_table = of_regulator_poweroff_match,
> + },
> +};
> +
> +module_platform_driver(regulator_poweroff_driver);
Since this can't be compiled as a module, you can use
module_platform_driver_probe instead.
Maxime
On Tue, Dec 08, 2020 at 11:10:52AM +0100, Maxime Ripard wrote:
>On Mon, Dec 07, 2020 at 03:27:54PM +0100, Michael Klein wrote:
>> This driver registers a pm_power_off function to disable a set of
>> regulators defined in the devicetree to turn off the board.
>>
>> Signed-off-by: Michael Klein <[email protected]>
>> ---
>> drivers/power/reset/Kconfig | 7 ++
>> drivers/power/reset/Makefile | 1 +
>> drivers/power/reset/regulator-poweroff.c | 107 +++++++++++++++++++++++
>> 3 files changed, 115 insertions(+)
>> create mode 100644 drivers/power/reset/regulator-poweroff.c
>>
>> diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
>> index d55b3727e00e..ae6cb7b0bd4d 100644
>> --- a/drivers/power/reset/Kconfig
>> +++ b/drivers/power/reset/Kconfig
>> @@ -177,6 +177,13 @@ config POWER_RESET_QNAP
>>
>> Say Y if you have a QNAP NAS.
>>
>> +config POWER_RESET_REGULATOR
>> + bool "Regulator subsystem power-off driver"
>> + depends on OF && REGULATOR
>> + help
>> + This driver supports turning off your board by disabling a set
>> + of regulators defined in the devicetree.
>> +
>> config POWER_RESET_RESTART
>> bool "Restart power-off driver"
>> help
>> diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
>> index c51eceba9ea3..9dc49d3a57ff 100644
>> --- a/drivers/power/reset/Makefile
>> +++ b/drivers/power/reset/Makefile
>> @@ -19,6 +19,7 @@ obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
>> obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o
>> obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
>> obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
>> +obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o
>> obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
>> obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o
>> obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o
>> diff --git a/drivers/power/reset/regulator-poweroff.c b/drivers/power/reset/regulator-poweroff.c
>> new file mode 100644
>> index 000000000000..df2ca4fdcc49
>> --- /dev/null
>> +++ b/drivers/power/reset/regulator-poweroff.c
>> @@ -0,0 +1,107 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Force-disables a regulator to power down a device
>> + *
>> + * Michael Klein <[email protected]>
>> + *
>> + * Copyright (C) 2020 Michael Klein
>> + *
>> + * Based on the gpio-poweroff driver.
>> + */
>> +#include <linux/delay.h>
>> +#include <linux/init.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regulator/consumer.h>
>> +
>> +#define DEFAULT_TIMEOUT_MS 3000
>> +
>> +/*
>> + * Hold configuration here, cannot be more than one instance of the driver
>> + * since pm_power_off itself is global.
>> + */
>> +static struct regulator **poweroff_regulators;
>> +static u32 timeout = DEFAULT_TIMEOUT_MS;
>> +
>> +static void regulator_poweroff_do_poweroff(void)
>> +{
>> + struct regulator **it;
>> +
>> + if (poweroff_regulators)
>> + for (it = poweroff_regulators; *it; ++it)
>> + if (regulator_is_enabled(*it))
>> + regulator_force_disable(*it);
>> +
>> + /* give it some time */
>> + mdelay(timeout);
>> +
>> + WARN_ON(1);
>> +}
>> +
>> +static int regulator_poweroff_probe(struct platform_device *pdev)
>> +{
>> + int count;
>> + const char *name;
>> + struct regulator **it;
>> + struct property *prop;
>> + struct device_node *node = pdev->dev.of_node;
>> +
>> + /* If a pm_power_off function has already been added, leave it alone */
>> + if (pm_power_off != NULL) {
>> + dev_err(&pdev->dev,
>> + "%s: pm_power_off function already registered\n",
>> + __func__);
>> + return -EBUSY;
>> + }
>> +
>> + count = of_property_count_strings(node, "regulator-names");
>> + if (count <= 0)
>> + return -ENOENT;
>> +
>> + poweroff_regulators = devm_kcalloc(&pdev->dev, count + 1,
>> + sizeof(struct regulator *), GFP_KERNEL);
>> +
>> + it = poweroff_regulators;
>> + of_property_for_each_string(node, "regulator-names", prop, name) {
>> + *it = devm_regulator_get(&pdev->dev, name);
>> + if (IS_ERR(*it))
>> + return PTR_ERR(*it);
>> + it++;
>> + }
>> +
>> + of_property_read_u32(node, "timeout-ms", &timeout);
>> +
>> + pm_power_off = ®ulator_poweroff_do_poweroff;
>> + return 0;
>> +}
>> +
>> +static int regulator_poweroff_remove(__maybe_unused struct platform_device *pdev)
>> +{
>> + if (pm_power_off == ®ulator_poweroff_do_poweroff)
>> + pm_power_off = NULL;
>> +
>> + return 0;
>> +}
>> +
>> +static const struct of_device_id of_regulator_poweroff_match[] = {
>> + { .compatible = "regulator-poweroff", },
>> + {},
>> +};
>> +
>> +static struct platform_driver regulator_poweroff_driver = {
>> + .probe = regulator_poweroff_probe,
>> + .remove = regulator_poweroff_remove,
>> + .driver = {
>> + .name = "poweroff-regulator",
>> + .of_match_table = of_regulator_poweroff_match,
>> + },
>> +};
>> +
>> +module_platform_driver(regulator_poweroff_driver);
>
>Since this can't be compiled as a module, you can use
>module_platform_driver_probe instead.
actually no, as platform_driver_probe() does not support deferred
probing and the regulator might not be available during
regulator_poweroff_probe() yet:
# dmesg | grep poweroff
[ 0.788135] poweroff-regulator poweroff: probe deferral not supported
--
Michael