Skip to contentSkip to conversation

GPIO driver to turn power off

PATCH New Andrew Lunn 3 participants 12 messages Nov 17, 2012 – Nov 21, 2012

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

v3 cover GPIO driver to turn power off

A few of the Kirkwood systems use a GPIO line to turn the power off on shutdown. They request the GPIO line in the board setup code, optionally setting it as an output and driving it inactive. They then register a function for pm_power_off. At the end of the shutdown, this function is called. The GPIO line is configured as an output, if not already so, and then driven active. In order to cover the use case of edges rather then levels, triggering power off, the GPIO line is then toggled active and later inactive. This should allow the driver to be used by PXA which also has boards using the same scheme.

The driver code was initially developed by Jamie Lentin and extended to cover the PXA case by Andrew Lunn.

v1 -> v2: Moved to drivers/power/reset
v2 -> v3: Fixed polarity of IB62x0 GPIO
Increased delay before WARN if the power does not go off.

Andrew Lunn (2):
ARM: Kirkwood: Convert DNSKW to use gpio-poweroff.
ARM: Kirkwood: Convert IB62x0 to use gpio-poweroff.

Jamie Lentin (1):
power: Add simple poweroff-gpio driver

 .../devicetree/bindings/gpio/gpio-poweroff.txt     |   22 ++++
 arch/arm/boot/dts/kirkwood-dnskw.dtsi              |    5 +
 arch/arm/boot/dts/kirkwood-ib62x0.dts              |    6 +
 arch/arm/mach-kirkwood/Kconfig                     |    4 +
 arch/arm/mach-kirkwood/board-dnskw.c               |   12 --
 arch/arm/mach-kirkwood/board-ib62x0.c              |   13 --
 drivers/power/Kconfig                              |    3 +
 drivers/power/Makefile                             |    1 +
 drivers/power/reset/Kconfig                        |   15 +++
 drivers/power/reset/Makefile                       |    1 +
 drivers/power/reset/gpio-poweroff.c                |  129 ++++++++++++++++++++
 11 files changed, 186 insertions(+), 25 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
 create mode 100644 drivers/power/reset/Kconfig
 create mode 100644 drivers/power/reset/Makefile
 create mode 100644 drivers/power/reset/gpio-poweroff.c
Signature · 1 line
1.7.10.4
#1 lore raw

PATCH v3 1/3 power: Add simple poweroff-gpio driver

From: Jamie Lentin <[email protected]>

Given appropriate devicetree bindings, this driver registers a pm_power_off function to set a GPIO line high/low to power down your board.

---
 .../devicetree/bindings/gpio/gpio-poweroff.txt     |   22 ++++
 drivers/power/Kconfig                              |    3 +
 drivers/power/Makefile                             |    1 +
 drivers/power/reset/Kconfig                        |   15 +++
 drivers/power/reset/Makefile                       |    1 +
 drivers/power/reset/gpio-poweroff.c                |  129 ++++++++++++++++++++
 6 files changed, 171 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
 create mode 100644 drivers/power/reset/Kconfig
 create mode 100644 drivers/power/reset/Makefile
 create mode 100644 drivers/power/reset/gpio-poweroff.c
Documentation/devicetree/bindings/gpio/gpio-poweroff.txt new file +22 -0
new file mode 100644
index 0000000..558cdf3
@@ -0,0 +1,22 @@
+GPIO line that should be set high/low to power off a device
+
+Required properties:
+- compatible : should be "gpio-poweroff".
+- gpios : The GPIO to set high/low, see "gpios property" in
+  Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be
+  low to power down the board set it to "Active Low", otherwise set
+  gpio to "Active High".
+
+Optional properties:
+- input : Initially configure the GPIO line as an input. Only reconfigure
+  it to an output when the pm_power_off function is called. If this optional
+  property is not specified, the GPIO is initialized as an output in its
+  inactive state.
+
+
+Examples:
+
+gpio-poweroff {
+	compatible = "gpio-poweroff";
+	gpios = <&gpio 4 0>; /* GPIO 4 Active Low */
+};
drivers/power/Kconfig +3 -0
index 49a8939..b1d956d 100644
@@ -335,6 +335,9 @@ config AB8500_BATTERY_THERM_ON_BATCTRL
 	help
 	  Say Y to enable battery temperature measurements using
 	  thermistor connected on BATCTRL ADC.
+
+source "drivers/power/reset/Kconfig"
+
 endif # POWER_SUPPLY
 
 source "drivers/power/avs/Kconfig"
drivers/power/Makefile +1 -0
index b949cf8..f1d99f4 100644
@@ -49,3 +49,4 @@ obj-$(CONFIG_CHARGER_MAX8997)	+= max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)	+= max8998_charger.o
 obj-$(CONFIG_POWER_AVS)		+= avs/
 obj-$(CONFIG_CHARGER_SMB347)	+= smb347-charger.o
+obj-$(CONFIG_POWER_RESET)	+= reset/
drivers/power/reset/Kconfig new file +15 -0
new file mode 100644
index 0000000..6461b48
@@ -0,0 +1,15 @@
+menuconfig POWER_RESET
+	bool "Board level reset or power off"
+	help
+	  Provides a number of drivers which either reset a complete board
+	  or shut it down, by manipulating the main power supply on the board.
+
+	  Say Y here to enable board reset and power off
+
+config POWER_RESET_GPIO
+	bool "GPIO power-off driver"
+	depends on OF_GPIO && POWER_RESET
+	help
+	  This driver supports turning off your board via a GPIO line.
+	  If your board needs a GPIO high/low to power down, say Y and
+	  create a binding in your devicetree.
drivers/power/reset/Makefile new file +1 -0
new file mode 100644
index 0000000..751488a
@@ -0,0 +1 @@
+obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
drivers/power/reset/gpio-poweroff.c new file +129 -0

129 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#2 lore raw

PATCH v3 1/3 power: Add simple poweroff-gpio driver

Quoted 7 lines · Andrew Lunn

Given appropriate devicetree bindings, this driver registers a pm_power_off function to set a GPIO line high/low to power down your board.

drivers/power/reset/Kconfig +1 -0
 
+menuconfig POWER_RESET

drivers/power/reset/Kconfig line 11

Quoted 10 lines
drivers/power/reset/Kconfig +10 -0
+	bool "Board level reset or power off"
+	help
+	  Provides a number of drivers which either reset a complete board
+	  or shut it down, by manipulating the main power supply on the board.
+
+	  Say Y here to enable board reset and power off
+
+config POWER_RESET_GPIO
+	bool "GPIO power-off driver"
+	depends on OF_GPIO && POWER_RESET

I assume CONFIG_POWER_RESET won't really provide any/much infra-structure itself. So, does it make sense to put all the individual drives inside "if POWER_RESET" or a menu definition, so they don't all have to depend on POWER_RESET explicitly?

drivers/power/reset/gpio-poweroff.c line 32

Quoted 5 lines
drivers/power/reset/gpio-poweroff.c +3 -0
 
+static void gpio_poweroff_do_poweroff(void)
+{
+	BUG_ON(gpio_num == -1);

Perhaps use gpio_is_valid() here?

drivers/power/reset/gpio-poweroff.c line 35

Quoted 2 lines
drivers/power/reset/gpio-poweroff.c +2 -0
+	/* drive it active */
+	gpio_direction_output(gpio_num, !gpio_active_low);

The rest of the code below doesn't make a lot of sense to me. From reading the binding documentation, it seems like the GPIO is expected to be level-sensitive, and as such the above gpio_direction_output() call should be all that's needed. What is the code below doing? If this driver supports either a level-sensitive GPIO or generating a pulse on a GPIO, I think the binding should be enhanced to specify which signalling type is required. Also, all the delays should be specified as DT properties.

drivers/power/reset/gpio-poweroff.c line 37

Quoted 2 lines
drivers/power/reset/gpio-poweroff.c +2 -0
+	mdelay(100);
+	/* rising edge or drive inactive */

You can't assume that an active->inactive edge is a rising edge if you allow the polarity to be configurable; I would remove that part of the comment. Same below for "falling edge".

drivers/power/reset/gpio-poweroff.c line 63

Quoted 12 lines
drivers/power/reset/gpio-poweroff.c +10 -0
+	gpio_set_value(gpio_num, gpio_active_low);
+	mdelay(100);
+	/* falling edge */
+	gpio_set_value(gpio_num, !gpio_active_low);
+
+	/* give it some time */
+	mdelay(3000);
 
+static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
 
+	gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
+	if (gpio_num < 0) {

Perhaps use gpio_is_valid() here?

drivers/power/reset/gpio-poweroff.c line 67

Quoted 4 lines
drivers/power/reset/gpio-poweroff.c +4 -0
+		pr_err("%s: Could not get GPIO configuration: %d",
+		       __func__, gpio_num);
+		return -ENODEV;
+	}

This doesn't handle deferred probe correctly; if gpio_num == -EPROBE_DEFER, then this function needs to return -EPROBE_DEFER too; why not "return gpio_num" rather than "return -ENODEV" above?

drivers/power/reset/gpio-poweroff.c line 71

Quoted 4 lines
drivers/power/reset/gpio-poweroff.c +4 -0
+	gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+	if (of_get_property(pdev->dev.of_node, "input", NULL))
+		input = true;

Perhaps use of_property_read_bool() here.

drivers/power/reset/gpio-poweroff.c line 102

Quoted 4 lines
drivers/power/reset/gpio-poweroff.c +4 -0
+static int __devexit gpio_poweroff_remove(struct platform_device *pdev)
+{
+	if (gpio_num != -1)
+		gpio_free(gpio_num);

Perhaps use gpio_is_valid() here? Actually, how could this happen; presumably if the GPIO is valid, probe() never succeeded, so you should always just free the GPIO.

drivers/power/reset/gpio-poweroff.c line 121

Quoted 8 lines
drivers/power/reset/gpio-poweroff.c +8 -0
+static struct platform_driver gpio_poweroff_driver = {
+	.probe = gpio_poweroff_probe,
+	.remove = __devexit_p(gpio_poweroff_remove),
+	.driver = {
+		   .name = "poweroff-gpio",
+		   .owner = THIS_MODULE,
+		   .of_match_table = of_gpio_poweroff_match,
+		   },

There seems to be a mix of TAB/space indents there, and the closing } should probably be aligned with the start of ".driver"?

Quoted 1 line

+MODULE_LICENSE("GPL");

That should be "GPL v2".

#3 lore raw

PATCH v3 1/3 power: Add simple poweroff-gpio driver

Hi Jason

These are good comments from Stephan that i want to address. However, i also don't want to delay the pull-requests direction arm-soc, the merge window is getting close. Both Linus and Anton have Acked the current version, so please go with what you have and i will produce a patch over the top. If its available before Arnd pulls, you can squash it, otherwise send it upstream as a standalone patch.

Thanks
Andrew

Quoted 106 lines · Stephen Warren
Quoted 7 lines · Andrew Lunn

Given appropriate devicetree bindings, this driver registers a pm_power_off function to set a GPIO line high/low to power down your board.

drivers/power/reset/Kconfig +1 -0
 
+menuconfig POWER_RESET

drivers/power/reset/Kconfig line 11

Quoted 10 lines
drivers/power/reset/Kconfig +10 -0
+	bool "Board level reset or power off"
+	help
+	  Provides a number of drivers which either reset a complete board
+	  or shut it down, by manipulating the main power supply on the board.
+
+	  Say Y here to enable board reset and power off
+
+config POWER_RESET_GPIO
+	bool "GPIO power-off driver"
+	depends on OF_GPIO && POWER_RESET

I assume CONFIG_POWER_RESET won't really provide any/much infra-structure itself. So, does it make sense to put all the individual drives inside "if POWER_RESET" or a menu definition, so they don't all have to depend on POWER_RESET explicitly?

drivers/power/reset/gpio-poweroff.c line 32

Quoted 5 lines
drivers/power/reset/gpio-poweroff.c +3 -0
 
+static void gpio_poweroff_do_poweroff(void)
+{
+	BUG_ON(gpio_num == -1);

Perhaps use gpio_is_valid() here?

drivers/power/reset/gpio-poweroff.c line 35

Quoted 2 lines
drivers/power/reset/gpio-poweroff.c +2 -0
+	/* drive it active */
+	gpio_direction_output(gpio_num, !gpio_active_low);

The rest of the code below doesn't make a lot of sense to me. From reading the binding documentation, it seems like the GPIO is expected to be level-sensitive, and as such the above gpio_direction_output() call should be all that's needed. What is the code below doing? If this driver supports either a level-sensitive GPIO or generating a pulse on a GPIO, I think the binding should be enhanced to specify which signalling type is required. Also, all the delays should be specified as DT properties.

drivers/power/reset/gpio-poweroff.c line 37

Quoted 2 lines
drivers/power/reset/gpio-poweroff.c +2 -0
+	mdelay(100);
+	/* rising edge or drive inactive */

You can't assume that an active->inactive edge is a rising edge if you allow the polarity to be configurable; I would remove that part of the comment. Same below for "falling edge".

drivers/power/reset/gpio-poweroff.c line 63

Quoted 12 lines
drivers/power/reset/gpio-poweroff.c +10 -0
+	gpio_set_value(gpio_num, gpio_active_low);
+	mdelay(100);
+	/* falling edge */
+	gpio_set_value(gpio_num, !gpio_active_low);
+
+	/* give it some time */
+	mdelay(3000);
 
+static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
 
+	gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
+	if (gpio_num < 0) {

Perhaps use gpio_is_valid() here?

drivers/power/reset/gpio-poweroff.c line 67

Quoted 4 lines
drivers/power/reset/gpio-poweroff.c +4 -0
+		pr_err("%s: Could not get GPIO configuration: %d",
+		       __func__, gpio_num);
+		return -ENODEV;
+	}

This doesn't handle deferred probe correctly; if gpio_num == -EPROBE_DEFER, then this function needs to return -EPROBE_DEFER too; why not "return gpio_num" rather than "return -ENODEV" above?

drivers/power/reset/gpio-poweroff.c line 71

Quoted 4 lines
drivers/power/reset/gpio-poweroff.c +4 -0
+	gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+	if (of_get_property(pdev->dev.of_node, "input", NULL))
+		input = true;

Perhaps use of_property_read_bool() here.

drivers/power/reset/gpio-poweroff.c line 102

Quoted 4 lines
drivers/power/reset/gpio-poweroff.c +4 -0
+static int __devexit gpio_poweroff_remove(struct platform_device *pdev)
+{
+	if (gpio_num != -1)
+		gpio_free(gpio_num);

Perhaps use gpio_is_valid() here? Actually, how could this happen; presumably if the GPIO is valid, probe() never succeeded, so you should always just free the GPIO.

drivers/power/reset/gpio-poweroff.c line 121

Quoted 8 lines
drivers/power/reset/gpio-poweroff.c +8 -0
+static struct platform_driver gpio_poweroff_driver = {
+	.probe = gpio_poweroff_probe,
+	.remove = __devexit_p(gpio_poweroff_remove),
+	.driver = {
+		   .name = "poweroff-gpio",
+		   .owner = THIS_MODULE,
+		   .of_match_table = of_gpio_poweroff_match,
+		   },

There seems to be a mix of TAB/space indents there, and the closing } should probably be aligned with the start of ".driver"?

Quoted 1 line

+MODULE_LICENSE("GPL");

That should be "GPL v2".

#4 lore raw

PATCH v3 1/3 power: Add simple poweroff-gpio driver

Quoted 6 lines · Andrew Lunn

These are good comments from Stephan that i want to address. However, i also don't want to delay the pull-requests direction arm-soc, the merge window is getting close. Both Linus and Anton have Acked the current version, so please go with what you have and i will produce a patch over the top. If its available before Arnd pulls, you can squash it, otherwise send it upstream as a standalone patch.

I agree. Furthermore, for the fixup patch, if it goes separately, you might want to add

to give a credit for the valuable comments. :)

#5 lore raw

PATCH v3 1/3 power: Add simple poweroff-gpio driver

In reply to Andrew Lunn
Quoted 8 lines · Andrew Lunn

Hi Jason

These are good comments from Stephan that i want to address. However, i also don't want to delay the pull-requests direction arm-soc, the merge window is getting close. Both Linus and Anton have Acked the current version, so please go with what you have and i will produce a patch over the top. If its available before Arnd pulls, you can squash it, otherwise send it upstream as a standalone patch.

I'm not sure I agree here; the comments I made re: the delays and pulse-vs-level may affect the definition of the DT binding, and that's something that should be correct from the start.

The implementation of gpio_poweroff_do_poweroff() really doesn't seem to make sense; related to the above.

Also, probe deferral doesn't work, which will likely make this code completely ineffective.

#6 lore raw

PATCH v3 1/3 power: Add simple poweroff-gpio driver

Quoted 10 lines · Stephen Warren
Quoted 8 lines · Andrew Lunn

Hi Jason

These are good comments from Stephan that i want to address. However, i also don't want to delay the pull-requests direction arm-soc, the merge window is getting close. Both Linus and Anton have Acked the current version, so please go with what you have and i will produce a patch over the top. If its available before Arnd pulls, you can squash it, otherwise send it upstream as a standalone patch.

Quoted 3 lines

I'm not sure I agree here; the comments I made re: the delays and pulse-vs-level may affect the definition of the DT binding, and that's something that should be correct from the start.

Hi Stephen

There should be no need to change the binding is a none-backwards compatible way. The current delays work for all current users. If some other user comes along which needs longer delays, they can add an optional property which specified a longer delay.

The pulse-vs-level is needed for the potential PXA use case, which is where i took this code from. When we first proposed this driver, Russel King pointed to the PXA reset.c code and requested we create something which PXA could use. The configuring the GPIO as an input also come from PXA, which the current two uses user don't need.

I agree it need better documentation, but the current code covers all bases. It will turn off a level based system, it will also turn off an edge based system. There is no need to specify in the DT which is needed, it will just work.

Quoted 5 lines

The implementation of gpio_poweroff_do_poweroff() really doesn't seem to make sense; related to the above.

Also, probe deferral doesn't work, which will likely make this code completely ineffective.

This code has been tested by the two current users. It works. However, i agree about your comment here, and i will fix it in the follow up patch.

Andrew

#7 lore raw

PATCH v3 1/3 power: Add simple poweroff-gpio driver

Quoted 11 lines · Andrew Lunn
Quoted 10 lines · Stephen Warren
Quoted 8 lines · Andrew Lunn

Hi Jason

These are good comments from Stephan that i want to address. However, i also don't want to delay the pull-requests direction arm-soc, the merge window is getting close. Both Linus and Anton have Acked the current version, so please go with what you have and i will produce a patch over the top. If its available before Arnd pulls, you can squash it, otherwise send it upstream as a standalone patch.

Quoted 8 lines
Quoted 3 lines

I'm not sure I agree here; the comments I made re: the delays and pulse-vs-level may affect the definition of the DT binding, and that's something that should be correct from the start.

Hi Stephen

There should be no need to change the binding is a none-backwards compatible way. The current delays work for all current users.

Well, the binding isn't written for current users, the description is just a generic "GPIO to turn off the system".

Quoted 3 lines

If some
other user comes along which needs longer delays, they can add an optional property which specified a longer delay.

The DT maintainers have in the past expressed a wish to define DT bindings completely, rather than incrementally adding stuff if at all possible. I guess they weren't CC'd on this patch; I've added them here for comment. I'll defer to whatever they think here.

Quoted 10 lines

The pulse-vs-level is needed for the potential PXA use case, which is where i took this code from. When we first proposed this driver, Russel King pointed to the PXA reset.c code and requested we create something which PXA could use. The configuring the GPIO as an input also come from PXA, which the current two uses user don't need.

I agree it need better documentation, but the current code covers all bases. It will turn off a level based system, it will also turn off an edge based system. There is no need to specify in the DT which is needed, it will just work.

I'm not convinced the pulse logic can be correct for arbitrary users who expect a level-sensitive GPIO; what if the MPU (or whatever the GPIO is connected to) is confused by the pulse and fails to power down when it sees a pulse (e.g. as a safety measure), but would have worked fine with just a regular level?

Quoted 9 lines
Quoted 5 lines

The implementation of gpio_poweroff_do_poweroff() really doesn't seem to make sense; related to the above.

Also, probe deferral doesn't work, which will likely make this code completely ineffective.

This code has been tested by the two current users. It works. However, i agree about your comment here, and i will fix it in the follow up patch.

If this were a specific driver just for certain platforms, I think it might be OK. Yet the driver purports to be generic. As such, I think we need to make it explicitly work for the general case, not just happen to work for the platforms that have been tested so far.

#8 lore raw

PATCH v3 1/3 power: Add simple poweroff-gpio driver

Quoted 16 lines · Stephen Warren
Quoted 15 lines · Andrew Lunn
Quoted 13 lines · Stephen Warren
Quoted 8 lines · Andrew Lunn

Hi Jason

These are good comments from Stephan that i want to address. However, i also don't want to delay the pull-requests direction arm-soc, the merge window is getting close. Both Linus and Anton have Acked the current version, so please go with what you have and i will produce a patch over the top. If its available before Arnd pulls, you can squash it, otherwise send it upstream as a standalone patch.

I'm not sure I agree here; the comments I made re: the delays and pulse-vs-level may affect the definition of the DT binding, and that's something that should be correct from the start.

Quoted 7 lines
Quoted 4 lines

Hi Stephen

There should be no need to change the binding is a none-backwards compatible way. The current delays work for all current users.

Well, the binding isn't written for current users, the description is just a generic "GPIO to turn off the system".

The current binding documentation is maybe lacking. But the binding itself fits the current users.

Quoted 8 lines
Quoted 3 lines

If some
other user comes along which needs longer delays, they can add an optional property which specified a longer delay.

The DT maintainers have in the past expressed a wish to define DT bindings completely, rather than incrementally adding stuff if at all possible. I guess they weren't CC'd on this patch; I've added them here for comment. I'll defer to whatever they think here.

They were CC: I learn't the hard way with a USB binding....

Quoted 11 lines
Quoted 10 lines

The pulse-vs-level is needed for the potential PXA use case, which is where i took this code from. When we first proposed this driver, Russel King pointed to the PXA reset.c code and requested we create something which PXA could use. The configuring the GPIO as an input also come from PXA, which the current two uses user don't need.

I agree it need better documentation, but the current code covers all bases. It will turn off a level based system, it will also turn off an edge based system. There is no need to specify in the DT which is needed, it will just work.

Quoted 5 lines

I'm not convinced the pulse logic can be correct for arbitrary users who expect a level-sensitive GPIO; what if the MPU (or whatever the GPIO is connected to) is confused by the pulse and fails to power down when it sees a pulse (e.g. as a safety measure), but would have worked fine with just a regular level?

Lets go through the sequence for a regular level off.....

At driver load time, assuming the optional input properties is not present, the GPIO line is driven inactive. At power down time, its driven active. One of four things can happen:

1) The power goes off. End of story

2) The delay is not long enough. In that case it goes inactive again, there is a short pause, and it goes active again, and the power goes off. End of story.

3) The delay is not long enough. In that case it goes inactive again, there is a short pause, and it goes active again. There is another pause, this time much longer. Still the power does not go off and we hit the WARN_ON(1); Some time after that, the power goes off. Not so nice, but at least the power went off eventually.

4) The delay is not long enough. In that case it goes inactive again, there is a short pause, and it goes active again. There is another pause, this time much longer. Still the power does not go off and we hit the WARN_ON(1); The power remains on, until somebody pulls the plug.

Your scenario is that a 100ms pulse confuses the MPU, and after that, it won't turn off given a much longer period of the gpio being active. We run into 4). Is that really likely? a 100ms is a long time. I could imaging a MPU ignoring a 1us pulse, or even a 1ms pulse. But a 100ms pulse? Also, after such a pulse, it simply refuses to turn off all together after 3000ms of active GPIO? Is that a general purpose piece of hardware which can be driven by a general purpose driver, or is it a specific piece of hardware which needs its own driver?

Quoted 4 lines

If this were a specific driver just for certain platforms, I think it might be OK. Yet the driver purports to be generic. As such, I think we need to make it explicitly work for the general case, not just happen to work for the platforms that have been tested so far.

And as i keep saying, i will submit a patch to fix this issue. It won't be tomorrow, but it won't be longer than a week.

Andrew

#9 lore raw

PATCH v3 1/3 power: Add simple poweroff-gpio driver

Quoted 32 lines · Andrew Lunn
Quoted 16 lines · Stephen Warren
Quoted 15 lines · Andrew Lunn
Quoted 13 lines · Stephen Warren
Quoted 8 lines · Andrew Lunn

Hi Jason

These are good comments from Stephan that i want to address. However, i also don't want to delay the pull-requests direction arm-soc, the merge window is getting close. Both Linus and Anton have Acked the current version, so please go with what you have and i will produce a patch over the top. If its available before Arnd pulls, you can squash it, otherwise send it upstream as a standalone patch.

I'm not sure I agree here; the comments I made re: the delays and pulse-vs-level may affect the definition of the DT binding, and that's something that should be correct from the start.

Quoted 7 lines
Quoted 4 lines

Hi Stephen

There should be no need to change the binding is a none-backwards compatible way. The current delays work for all current users.

Well, the binding isn't written for current users, the description is just a generic "GPIO to turn off the system".

The current binding documentation is maybe lacking. But the binding itself fits the current users.

Quoted 4 lines
Quoted 3 lines

If some
other user comes along which needs longer delays, they can add an optional property which specified a longer delay.

Quoted 6 lines
Quoted 4 lines

The DT maintainers have in the past expressed a wish to define DT bindings completely, rather than incrementally adding stuff if at all possible. I guess they weren't CC'd on this patch; I've added them here for comment. I'll defer to whatever they think here.

They were CC: I learn't the hard way with a USB binding....

Sorry to be picky, but I checked the original postings of the first rev and V3 and they didn't appear to be CC'd. The mailing list was, but not the people. I guess Grant did comment on the first rev though. He didn't give an opinion on the DT binding that I can find.

Quoted 22 lines
Quoted 11 lines
Quoted 10 lines

The pulse-vs-level is needed for the potential PXA use case, which is where i took this code from. When we first proposed this driver, Russel King pointed to the PXA reset.c code and requested we create something which PXA could use. The configuring the GPIO as an input also come from PXA, which the current two uses user don't need.

I agree it need better documentation, but the current code covers all bases. It will turn off a level based system, it will also turn off an edge based system. There is no need to specify in the DT which is needed, it will just work.

Quoted 5 lines

I'm not convinced the pulse logic can be correct for arbitrary users who expect a level-sensitive GPIO; what if the MPU (or whatever the GPIO is connected to) is confused by the pulse and fails to power down when it sees a pulse (e.g. as a safety measure), but would have worked fine with just a regular level?

Lets go through the sequence for a regular level off.....

At driver load time, assuming the optional input properties is not present, the GPIO line is driven inactive. At power down time, its driven active. One of four things can happen:

...

Quoted 9 lines

4) The delay is not long enough. In that case it goes inactive again, there is a short pause, and it goes active again. There is another pause, this time much longer. Still the power does not go off and we hit the WARN_ON(1); The power remains on, until somebody pulls the plug.

Your scenario is that a 100ms pulse confuses the MPU, and after that, it won't turn off given a much longer period of the gpio being active. We run into 4). Is that really likely?

Yes, (4) is my concern.

Honestly, I don't know if it's likely. It's certainly theoretically possible. Either way though, I'd rather the kernel explicitly drive the signal in the fashion that the specific HW expects it to be driven, rather than wiggling the GPIO in a way that by luck happens to work for a variety of disparate requirements.

Anyway, I've made my opinion clear. Whoever would merge this patch can choose to ignore it or not.

#10 lore raw

PATCH v3 2/3 ARM: Kirkwood: Convert DNSKW to use gpio-poweroff.

In reply to Andrew Lunn

Also enable the gpio-poweroff driver when DT is used.

---
 arch/arm/boot/dts/kirkwood-dnskw.dtsi |    5 +++++
 arch/arm/mach-kirkwood/Kconfig        |    4 ++++
 arch/arm/mach-kirkwood/board-dnskw.c  |   12 ------------
 3 files changed, 9 insertions(+), 12 deletions(-)
arch/arm/boot/dts/kirkwood-dnskw.dtsi +5 -0
index 9b32d02..22aa07a 100644
@@ -35,6 +35,11 @@
 				      6000 2>;
 	};
 
+	gpio_poweroff {
+		compatible = "gpio-poweroff";
+		gpios = <&gpio1 4 0>;
+	};
+
 	ocp at f1000000 {
 		sata at 80000 {
 			status = "okay";
arch/arm/mach-kirkwood/Kconfig +4 -0
index 50bca50..e0d26fe 100644
@@ -46,7 +46,11 @@ config MACH_GURUPLUG
 
 config ARCH_KIRKWOOD_DT
 	bool "Marvell Kirkwood Flattened Device Tree"
+	select POWER_SUPPLY
+	select POWER_RESET
+	select POWER_RESET_GPIO
 	select USE_OF
+
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell Kirkwood using flattened device tree.
arch/arm/mach-kirkwood/board-dnskw.c +0 -12
index 43d16d6..549369e 100644
@@ -57,11 +57,6 @@ static unsigned int dnskw_mpp_config[] __initdata = {
 	0
 };
 
-static void dnskw_power_off(void)
-{
-	gpio_set_value(36, 1);
-}
-
 /* Register any GPIO for output and set the value */
 static void __init dnskw_gpio_register(unsigned gpio, char *name, int def)
 {
@@ -81,13 +76,6 @@ void __init dnskw_init(void)
 	kirkwood_ehci_init();
 	kirkwood_ge00_init(&dnskw_ge00_data);
 
-	/* Register power-off GPIO. */
-	if (gpio_request(36, "dnskw:power:off") == 0
-	    && gpio_direction_output(36, 0) == 0)
-		pm_power_off = dnskw_power_off;
-	else
-		pr_err("dnskw: failed to configure power-off GPIO\n");
-
 	/* Ensure power is supplied to both HDDs */
 	dnskw_gpio_register(39, "dnskw:power:sata0", 1);
 	dnskw_gpio_register(40, "dnskw:power:sata1", 1);
Signature · 1 line
1.7.10.4
#11 lore raw

PATCH v3 3/3 ARM: Kirkwood: Convert IB62x0 to use gpio-poweroff.

In reply to Andrew Lunn
---
 arch/arm/boot/dts/kirkwood-ib62x0.dts |    6 ++++++
 arch/arm/mach-kirkwood/board-ib62x0.c |   13 -------------
 2 files changed, 6 insertions(+), 13 deletions(-)
arch/arm/boot/dts/kirkwood-ib62x0.dts +6 -0
index 66794ed..6a9558d 100644
@@ -79,4 +79,10 @@
 			gpios = <&gpio0 27 0>;
 		};
 	};
+	gpio_poweroff {
+		compatible = "gpio-poweroff";
+		gpios = <&gpio0 24 0>;
+	};
+
+
 };
arch/arm/mach-kirkwood/board-ib62x0.c +0 -13
index cfc47f8..7b8adf5 100644
@@ -17,7 +17,6 @@
 #include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
 #include <linux/input.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -25,8 +24,6 @@
 #include "common.h"
 #include "mpp.h"
 
-#define IB62X0_GPIO_POWER_OFF	24
-
 static struct mv643xx_eth_platform_data ib62x0_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
 };
@@ -49,11 +46,6 @@ static unsigned int ib62x0_mpp_config[] __initdata = {
 	0
 };
 
-static void ib62x0_power_off(void)
-{
-	gpio_set_value(IB62X0_GPIO_POWER_OFF, 1);
-}
-
 void __init ib62x0_init(void)
 {
 	/*
@@ -63,9 +55,4 @@ void __init ib62x0_init(void)
 
 	kirkwood_ehci_init();
 	kirkwood_ge00_init(&ib62x0_ge00_data);
-	if (gpio_request(IB62X0_GPIO_POWER_OFF, "ib62x0:power:off") == 0 &&
-	    gpio_direction_output(IB62X0_GPIO_POWER_OFF, 0) == 0)
-		pm_power_off = ib62x0_power_off;
-	else
-		pr_err("board-ib62x0: failed to configure power-off GPIO\n");
 }
Signature · 1 line
1.7.10.4