mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2] poweroff: Allow to register poweroff handlers
@ 2017-03-13 11:05 Oleksij Rempel
  2017-03-14  7:17 ` Sascha Hauer
  0 siblings, 1 reply; 2+ messages in thread
From: Oleksij Rempel @ 2017-03-13 11:05 UTC (permalink / raw)
  To: barebox; +Cc: Oleksij Rempel

From: Sascha Hauer <s.hauer@pengutronix.de>

Allow to register handlers for poweroff. This allows to have multiple
poweroff implementations in a single binary. The implementation is close
to the restart handlers.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 arch/arm/Kconfig                         |   2 -
 arch/arm/boards/mioa701/gpio0_poweroff.c |   3 +-
 arch/arm/mach-highbank/reset.c           |  20 +++---
 arch/arm/mach-pxa/pxa2xx.c               |  15 +++-
 arch/arm/mach-pxa/pxa3xx.c               |  13 +++-
 arch/mips/mach-xburst/Kconfig            |   1 -
 arch/mips/mach-xburst/reset-jz4750.c     |  13 +++-
 commands/Kconfig                         |   5 --
 commands/poweroff.c                      |   3 +-
 common/Makefile                          |   1 +
 common/poweroff.c                        | 114 +++++++++++++++++++++++++++++++
 include/common.h                         |   3 -
 include/poweroff.h                       |  21 ++++++
 13 files changed, 186 insertions(+), 28 deletions(-)
 create mode 100644 common/poweroff.c
 create mode 100644 include/poweroff.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3e8ccf766..eedc2b4e9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -98,7 +98,6 @@ config ARCH_EP93XX
 config ARCH_HIGHBANK
 	bool "Calxeda Highbank"
 	select HAS_DEBUG_LL
-	select HAS_POWEROFF
 	select ARCH_HAS_L2X0
 	select CPU_V7
 	select ARM_AMBA
@@ -158,7 +157,6 @@ config ARCH_OMAP
 config ARCH_PXA
 	bool "Intel/Marvell PXA based"
 	select GENERIC_GPIO
-	select HAS_POWEROFF
 
 config ARCH_ROCKCHIP
 	bool "Rockchip RX3xxx"
diff --git a/arch/arm/boards/mioa701/gpio0_poweroff.c b/arch/arm/boards/mioa701/gpio0_poweroff.c
index 2054548aa..01a5d0cc6 100644
--- a/arch/arm/boards/mioa701/gpio0_poweroff.c
+++ b/arch/arm/boards/mioa701/gpio0_poweroff.c
@@ -19,6 +19,7 @@
 #include <clock.h>
 #include <common.h>
 #include <init.h>
+#include <poweroff.h>
 #include <gpio.h>
 #include <poller.h>
 
@@ -45,7 +46,7 @@ static void try_poweroff(void)
 
 	gpio_set_value(GPIO115_LED_nKeyboard, 0);
 	mdelay(2000);
-	poweroff();
+	poweroff_machine();
 }
 
 static void gpio0_poller_fn(struct poller_struct *poller)
diff --git a/arch/arm/mach-highbank/reset.c b/arch/arm/mach-highbank/reset.c
index 929ded595..b60f34452 100644
--- a/arch/arm/mach-highbank/reset.c
+++ b/arch/arm/mach-highbank/reset.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <io.h>
+#include <poweroff.h>
 #include <restart.h>
 #include <init.h>
 
@@ -20,15 +21,7 @@ static void __noreturn highbank_restart_soc(struct restart_handler *rst)
 	hang();
 }
 
-static int restart_register_feature(void)
-{
-	restart_handler_register_fn(highbank_restart_soc);
-
-	return 0;
-}
-coredevice_initcall(restart_register_feature);
-
-void __noreturn poweroff()
+void __noreturn highbank_poweroff(struct poweroff_handler *handler)
 {
 	shutdown_barebox();
 
@@ -37,3 +30,12 @@ void __noreturn poweroff()
 
 	while(1);
 }
+
+static int highbank_init(void)
+{
+	restart_handler_register_fn(highbank_restart_soc);
+	poweroff_handler_register_fn(highbank_poweroff);
+
+	return 0;
+}
+coredevice_initcall(highbank_init);
diff --git a/arch/arm/mach-pxa/pxa2xx.c b/arch/arm/mach-pxa/pxa2xx.c
index b712b388c..e28378e6d 100644
--- a/arch/arm/mach-pxa/pxa2xx.c
+++ b/arch/arm/mach-pxa/pxa2xx.c
@@ -14,6 +14,7 @@
 
 #include <common.h>
 #include <init.h>
+#include <poweroff.h>
 #include <reset_source.h>
 #include <mach/hardware.h>
 #include <mach/pxa-regs.h>
@@ -46,9 +47,7 @@ void pxa_clear_reset_source(void)
 	RCSR = RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR;
 }
 
-device_initcall(pxa_detect_reset_source);
-
-void __noreturn poweroff(void)
+static void __noreturn pxa2xx_poweroff(struct poweroff_handler *handler)
 {
 	shutdown_barebox();
 
@@ -57,3 +56,13 @@ void __noreturn poweroff(void)
 	pxa_suspend(PWRMODE_DEEPSLEEP);
 	unreachable();
 }
+
+static int pxa2xx_init(void)
+{
+	poweroff_handler_register_fn(pxa2xx_poweroff);
+
+	pxa_detect_reset_source();
+
+	return 0;
+}
+device_initcall(pxa2xx_init);
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 86ca63b16..ccfd952b5 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -14,6 +14,7 @@
 
 #include <common.h>
 #include <init.h>
+#include <poweroff.h>
 #include <reset_source.h>
 #include <mach/hardware.h>
 #include <mach/pxa-regs.h>
@@ -48,7 +49,7 @@ void pxa_clear_reset_source(void)
 
 device_initcall(pxa_detect_reset_source);
 
-void __noreturn poweroff(void)
+static void __noreturn pxa3xx_poweroff(struct poweroff_handler *handler)
 {
 	shutdown_barebox();
 
@@ -57,3 +58,13 @@ void __noreturn poweroff(void)
 	pxa3xx_suspend(PXA3xx_PM_S3D4C4);
 	unreachable();
 }
+
+static int pxa3xx_init(void)
+{
+	poweroff_handler_register_fn(pxa3xx_poweroff);
+
+	pxa_detect_reset_source();
+
+	return 0;
+}
+device_initcall(pxa3xx_init);
diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig
index fd106fefe..ee79ff616 100644
--- a/arch/mips/mach-xburst/Kconfig
+++ b/arch/mips/mach-xburst/Kconfig
@@ -21,7 +21,6 @@ choice
 
 config BOARD_RZX50
 	bool "Ritmix RZX-50"
-	select HAS_POWEROFF
 	select CPU_JZ4755
 
 config BOARD_CI20
diff --git a/arch/mips/mach-xburst/reset-jz4750.c b/arch/mips/mach-xburst/reset-jz4750.c
index 25830f130..e1e88e2bf 100644
--- a/arch/mips/mach-xburst/reset-jz4750.c
+++ b/arch/mips/mach-xburst/reset-jz4750.c
@@ -22,6 +22,8 @@
 
 #include <common.h>
 #include <io.h>
+#include <init.h>
+#include <poweroff.h>
 #include <mach/jz4750d_regs.h>
 
 static void __noreturn jz4750d_halt(void)
@@ -37,7 +39,7 @@ static void __noreturn jz4750d_halt(void)
 	unreachable();
 }
 
-void __noreturn poweroff()
+static void __noreturn jz4750_poweroff(struct poweroff_handler *handler)
 {
 	u32 ctrl;
 
@@ -50,4 +52,11 @@ void __noreturn poweroff()
 	writel(RTC_HCR_PD, (u32 *)RTC_HCR);
 	jz4750d_halt();
 }
-EXPORT_SYMBOL(poweroff);
+
+static int jz4750_init(void)
+{
+	restart_handler_register_fn(jz4750_poweroff);
+
+	return 0;
+}
+coredevice_initcall(jz4750_init);
\ No newline at end of file
diff --git a/commands/Kconfig b/commands/Kconfig
index 21d921268..5a709a900 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -6,10 +6,6 @@ config COMMAND_SUPPORT
 	depends on !SHELL_NONE
 	default y
 
-config HAS_POWEROFF
-	bool
-	default n
-
 if COMMAND_SUPPORT
 
 config COMPILE_HASH
@@ -1848,7 +1844,6 @@ config CMD_NAND_BITFLIP
 
 config CMD_POWEROFF
 	tristate
-	depends on HAS_POWEROFF
 	prompt "poweroff"
 	help
 	  Turn the power off.
diff --git a/commands/poweroff.c b/commands/poweroff.c
index e8c726a7f..bbafa13bd 100644
--- a/commands/poweroff.c
+++ b/commands/poweroff.c
@@ -19,10 +19,11 @@
 
 #include <common.h>
 #include <command.h>
+#include <poweroff.h>
 
 static int cmd_poweroff(int argc, char *argv[])
 {
-	poweroff();
+	poweroff_machine();
 
 	/* Not reached */
 	return 1;
diff --git a/common/Makefile b/common/Makefile
index 869b15a92..572bf0578 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -9,6 +9,7 @@ obj-pbl-y			+= memsize.o
 obj-y				+= resource.o
 obj-y				+= bootsource.o
 obj-y				+= restart.o
+obj-y				+= poweroff.o
 obj-$(CONFIG_AUTO_COMPLETE)	+= complete.o
 obj-$(CONFIG_BANNER)		+= version.o
 obj-$(CONFIG_BAREBOX_UPDATE)	+= bbu.o
diff --git a/common/poweroff.c b/common/poweroff.c
new file mode 100644
index 000000000..32a78280d
--- /dev/null
+++ b/common/poweroff.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#define pr_fmt(fmt) "poweroff: " fmt
+
+#include <common.h>
+#include <poweroff.h>
+#include <malloc.h>
+#include <of.h>
+
+static LIST_HEAD(poweroff_handler_list);
+
+/**
+ * poweroff_handler_register() - register a handler for poweroffing the system
+ * @rst:	The handler struct
+ *
+ * This adds @rst to the list of registered poweroff handlers.
+ *
+ * return: 0 for success or negative error code
+ */
+int poweroff_handler_register(struct poweroff_handler *handler)
+{
+	if (!handler->name)
+		handler->name = POWEROFF_DEFAULT_NAME;
+	if (!handler->priority)
+		handler->priority = POWEROFF_DEFAULT_PRIORITY;
+
+	list_add_tail(&handler->list, &poweroff_handler_list);
+
+	pr_debug("registering poweroff handler \"%s\" with priority %d\n",
+			handler->name, handler->priority);
+
+	return 0;
+}
+
+/**
+ * poweroff_handler_register_fn() - register a handler function
+ * @poweroff_fn:	The poweroff function
+ *
+ * convenience wrapper for poweroff_handler_register() to register a handler
+ * with given function and default values otherwise.
+ *
+ * return: 0 for success or negative error code
+ */
+int poweroff_handler_register_fn(void (*poweroff_fn)(struct poweroff_handler *))
+{
+	struct poweroff_handler *handler;
+	int ret;
+
+	handler = xzalloc(sizeof(*handler));
+
+	handler->poweroff = poweroff_fn;
+
+	ret = poweroff_handler_register(handler);
+
+	if (ret)
+		free(handler);
+
+	return ret;
+}
+
+/**
+ * poweroff_machine() - power off the machine
+ */
+void __noreturn poweroff_machine(void)
+{
+	struct poweroff_handler *handler = NULL, *tmp;
+	unsigned int priority = 0;
+
+	list_for_each_entry(tmp, &poweroff_handler_list, list) {
+		if (tmp->priority > priority) {
+			priority = tmp->priority;
+			handler = tmp;
+		}
+	}
+
+	if (handler) {
+		pr_debug("using poweroff handler %s\n", handler->name);
+		console_flush();
+		handler->poweroff(handler);
+	} else {
+		pr_err("No poweroff handler found!\n");
+	}
+
+	hang();
+}
+
+/**
+ * of_get_poweroff_priority() - get the desired poweroff priority from device tree
+ * @node:	The device_node to read the property from
+ *
+ * return: The priority
+ */
+unsigned int of_get_poweroff_priority(struct device_node *node)
+{
+	unsigned int priority = POWEROFF_DEFAULT_PRIORITY;
+
+	of_property_read_u32(node, "poweroff-priority", &priority);
+
+	return priority;
+}
diff --git a/include/common.h b/include/common.h
index 680a0affb..dd7445e9b 100644
--- a/include/common.h
+++ b/include/common.h
@@ -66,9 +66,6 @@ int	readline	(const char *prompt, char *buf, int len);
 /* common/memsize.c */
 long	get_ram_size  (volatile long *, long);
 
-/* $(CPU)/cpu.c */
-void __noreturn poweroff(void);
-
 /* common/console.c */
 int	ctrlc (void);
 
diff --git a/include/poweroff.h b/include/poweroff.h
new file mode 100644
index 000000000..ae9557db5
--- /dev/null
+++ b/include/poweroff.h
@@ -0,0 +1,21 @@
+#ifndef __INCLUDE_POWEROFF_H
+#define __INCLUDE_POWEROFF_H
+
+void __noreturn poweroff_machine(void);
+
+struct poweroff_handler {
+	void (*poweroff)(struct poweroff_handler *);
+	int priority;
+	const char *name;
+	struct list_head list;
+};
+
+int poweroff_handler_register(struct poweroff_handler *);
+int poweroff_handler_register_fn(void (*poweroff_fn)(struct poweroff_handler *));
+
+#define POWEROFF_DEFAULT_PRIORITY 100
+#define POWEROFF_DEFAULT_NAME "default"
+
+unsigned int of_get_poweroff_priority(struct device_node *node);
+
+#endif /* __INCLUDE_POWEROFF_H */
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] poweroff: Allow to register poweroff handlers
  2017-03-13 11:05 [PATCH v2] poweroff: Allow to register poweroff handlers Oleksij Rempel
@ 2017-03-14  7:17 ` Sascha Hauer
  0 siblings, 0 replies; 2+ messages in thread
From: Sascha Hauer @ 2017-03-14  7:17 UTC (permalink / raw)
  To: Oleksij Rempel; +Cc: barebox

On Mon, Mar 13, 2017 at 12:05:23PM +0100, Oleksij Rempel wrote:
> From: Sascha Hauer <s.hauer@pengutronix.de>
> 
> Allow to register handlers for poweroff. This allows to have multiple
> poweroff implementations in a single binary. The implementation is close
> to the restart handlers.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>

Applied, thanks

Sascha

> ---
>  arch/arm/Kconfig                         |   2 -
>  arch/arm/boards/mioa701/gpio0_poweroff.c |   3 +-
>  arch/arm/mach-highbank/reset.c           |  20 +++---
>  arch/arm/mach-pxa/pxa2xx.c               |  15 +++-
>  arch/arm/mach-pxa/pxa3xx.c               |  13 +++-
>  arch/mips/mach-xburst/Kconfig            |   1 -
>  arch/mips/mach-xburst/reset-jz4750.c     |  13 +++-
>  commands/Kconfig                         |   5 --
>  commands/poweroff.c                      |   3 +-
>  common/Makefile                          |   1 +
>  common/poweroff.c                        | 114 +++++++++++++++++++++++++++++++
>  include/common.h                         |   3 -
>  include/poweroff.h                       |  21 ++++++
>  13 files changed, 186 insertions(+), 28 deletions(-)
>  create mode 100644 common/poweroff.c
>  create mode 100644 include/poweroff.h
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 3e8ccf766..eedc2b4e9 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -98,7 +98,6 @@ config ARCH_EP93XX
>  config ARCH_HIGHBANK
>  	bool "Calxeda Highbank"
>  	select HAS_DEBUG_LL
> -	select HAS_POWEROFF
>  	select ARCH_HAS_L2X0
>  	select CPU_V7
>  	select ARM_AMBA
> @@ -158,7 +157,6 @@ config ARCH_OMAP
>  config ARCH_PXA
>  	bool "Intel/Marvell PXA based"
>  	select GENERIC_GPIO
> -	select HAS_POWEROFF
>  
>  config ARCH_ROCKCHIP
>  	bool "Rockchip RX3xxx"
> diff --git a/arch/arm/boards/mioa701/gpio0_poweroff.c b/arch/arm/boards/mioa701/gpio0_poweroff.c
> index 2054548aa..01a5d0cc6 100644
> --- a/arch/arm/boards/mioa701/gpio0_poweroff.c
> +++ b/arch/arm/boards/mioa701/gpio0_poweroff.c
> @@ -19,6 +19,7 @@
>  #include <clock.h>
>  #include <common.h>
>  #include <init.h>
> +#include <poweroff.h>
>  #include <gpio.h>
>  #include <poller.h>
>  
> @@ -45,7 +46,7 @@ static void try_poweroff(void)
>  
>  	gpio_set_value(GPIO115_LED_nKeyboard, 0);
>  	mdelay(2000);
> -	poweroff();
> +	poweroff_machine();
>  }
>  
>  static void gpio0_poller_fn(struct poller_struct *poller)
> diff --git a/arch/arm/mach-highbank/reset.c b/arch/arm/mach-highbank/reset.c
> index 929ded595..b60f34452 100644
> --- a/arch/arm/mach-highbank/reset.c
> +++ b/arch/arm/mach-highbank/reset.c
> @@ -6,6 +6,7 @@
>  
>  #include <common.h>
>  #include <io.h>
> +#include <poweroff.h>
>  #include <restart.h>
>  #include <init.h>
>  
> @@ -20,15 +21,7 @@ static void __noreturn highbank_restart_soc(struct restart_handler *rst)
>  	hang();
>  }
>  
> -static int restart_register_feature(void)
> -{
> -	restart_handler_register_fn(highbank_restart_soc);
> -
> -	return 0;
> -}
> -coredevice_initcall(restart_register_feature);
> -
> -void __noreturn poweroff()
> +void __noreturn highbank_poweroff(struct poweroff_handler *handler)
>  {
>  	shutdown_barebox();
>  
> @@ -37,3 +30,12 @@ void __noreturn poweroff()
>  
>  	while(1);
>  }
> +
> +static int highbank_init(void)
> +{
> +	restart_handler_register_fn(highbank_restart_soc);
> +	poweroff_handler_register_fn(highbank_poweroff);
> +
> +	return 0;
> +}
> +coredevice_initcall(highbank_init);
> diff --git a/arch/arm/mach-pxa/pxa2xx.c b/arch/arm/mach-pxa/pxa2xx.c
> index b712b388c..e28378e6d 100644
> --- a/arch/arm/mach-pxa/pxa2xx.c
> +++ b/arch/arm/mach-pxa/pxa2xx.c
> @@ -14,6 +14,7 @@
>  
>  #include <common.h>
>  #include <init.h>
> +#include <poweroff.h>
>  #include <reset_source.h>
>  #include <mach/hardware.h>
>  #include <mach/pxa-regs.h>
> @@ -46,9 +47,7 @@ void pxa_clear_reset_source(void)
>  	RCSR = RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR;
>  }
>  
> -device_initcall(pxa_detect_reset_source);
> -
> -void __noreturn poweroff(void)
> +static void __noreturn pxa2xx_poweroff(struct poweroff_handler *handler)
>  {
>  	shutdown_barebox();
>  
> @@ -57,3 +56,13 @@ void __noreturn poweroff(void)
>  	pxa_suspend(PWRMODE_DEEPSLEEP);
>  	unreachable();
>  }
> +
> +static int pxa2xx_init(void)
> +{
> +	poweroff_handler_register_fn(pxa2xx_poweroff);
> +
> +	pxa_detect_reset_source();
> +
> +	return 0;
> +}
> +device_initcall(pxa2xx_init);
> diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
> index 86ca63b16..ccfd952b5 100644
> --- a/arch/arm/mach-pxa/pxa3xx.c
> +++ b/arch/arm/mach-pxa/pxa3xx.c
> @@ -14,6 +14,7 @@
>  
>  #include <common.h>
>  #include <init.h>
> +#include <poweroff.h>
>  #include <reset_source.h>
>  #include <mach/hardware.h>
>  #include <mach/pxa-regs.h>
> @@ -48,7 +49,7 @@ void pxa_clear_reset_source(void)
>  
>  device_initcall(pxa_detect_reset_source);
>  
> -void __noreturn poweroff(void)
> +static void __noreturn pxa3xx_poweroff(struct poweroff_handler *handler)
>  {
>  	shutdown_barebox();
>  
> @@ -57,3 +58,13 @@ void __noreturn poweroff(void)
>  	pxa3xx_suspend(PXA3xx_PM_S3D4C4);
>  	unreachable();
>  }
> +
> +static int pxa3xx_init(void)
> +{
> +	poweroff_handler_register_fn(pxa3xx_poweroff);
> +
> +	pxa_detect_reset_source();
> +
> +	return 0;
> +}
> +device_initcall(pxa3xx_init);
> diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig
> index fd106fefe..ee79ff616 100644
> --- a/arch/mips/mach-xburst/Kconfig
> +++ b/arch/mips/mach-xburst/Kconfig
> @@ -21,7 +21,6 @@ choice
>  
>  config BOARD_RZX50
>  	bool "Ritmix RZX-50"
> -	select HAS_POWEROFF
>  	select CPU_JZ4755
>  
>  config BOARD_CI20
> diff --git a/arch/mips/mach-xburst/reset-jz4750.c b/arch/mips/mach-xburst/reset-jz4750.c
> index 25830f130..e1e88e2bf 100644
> --- a/arch/mips/mach-xburst/reset-jz4750.c
> +++ b/arch/mips/mach-xburst/reset-jz4750.c
> @@ -22,6 +22,8 @@
>  
>  #include <common.h>
>  #include <io.h>
> +#include <init.h>
> +#include <poweroff.h>
>  #include <mach/jz4750d_regs.h>
>  
>  static void __noreturn jz4750d_halt(void)
> @@ -37,7 +39,7 @@ static void __noreturn jz4750d_halt(void)
>  	unreachable();
>  }
>  
> -void __noreturn poweroff()
> +static void __noreturn jz4750_poweroff(struct poweroff_handler *handler)
>  {
>  	u32 ctrl;
>  
> @@ -50,4 +52,11 @@ void __noreturn poweroff()
>  	writel(RTC_HCR_PD, (u32 *)RTC_HCR);
>  	jz4750d_halt();
>  }
> -EXPORT_SYMBOL(poweroff);
> +
> +static int jz4750_init(void)
> +{
> +	restart_handler_register_fn(jz4750_poweroff);
> +
> +	return 0;
> +}
> +coredevice_initcall(jz4750_init);
> \ No newline at end of file
> diff --git a/commands/Kconfig b/commands/Kconfig
> index 21d921268..5a709a900 100644
> --- a/commands/Kconfig
> +++ b/commands/Kconfig
> @@ -6,10 +6,6 @@ config COMMAND_SUPPORT
>  	depends on !SHELL_NONE
>  	default y
>  
> -config HAS_POWEROFF
> -	bool
> -	default n
> -
>  if COMMAND_SUPPORT
>  
>  config COMPILE_HASH
> @@ -1848,7 +1844,6 @@ config CMD_NAND_BITFLIP
>  
>  config CMD_POWEROFF
>  	tristate
> -	depends on HAS_POWEROFF
>  	prompt "poweroff"
>  	help
>  	  Turn the power off.
> diff --git a/commands/poweroff.c b/commands/poweroff.c
> index e8c726a7f..bbafa13bd 100644
> --- a/commands/poweroff.c
> +++ b/commands/poweroff.c
> @@ -19,10 +19,11 @@
>  
>  #include <common.h>
>  #include <command.h>
> +#include <poweroff.h>
>  
>  static int cmd_poweroff(int argc, char *argv[])
>  {
> -	poweroff();
> +	poweroff_machine();
>  
>  	/* Not reached */
>  	return 1;
> diff --git a/common/Makefile b/common/Makefile
> index 869b15a92..572bf0578 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -9,6 +9,7 @@ obj-pbl-y			+= memsize.o
>  obj-y				+= resource.o
>  obj-y				+= bootsource.o
>  obj-y				+= restart.o
> +obj-y				+= poweroff.o
>  obj-$(CONFIG_AUTO_COMPLETE)	+= complete.o
>  obj-$(CONFIG_BANNER)		+= version.o
>  obj-$(CONFIG_BAREBOX_UPDATE)	+= bbu.o
> diff --git a/common/poweroff.c b/common/poweroff.c
> new file mode 100644
> index 000000000..32a78280d
> --- /dev/null
> +++ b/common/poweroff.c
> @@ -0,0 +1,114 @@
> +/*
> + * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +#define pr_fmt(fmt) "poweroff: " fmt
> +
> +#include <common.h>
> +#include <poweroff.h>
> +#include <malloc.h>
> +#include <of.h>
> +
> +static LIST_HEAD(poweroff_handler_list);
> +
> +/**
> + * poweroff_handler_register() - register a handler for poweroffing the system
> + * @rst:	The handler struct
> + *
> + * This adds @rst to the list of registered poweroff handlers.
> + *
> + * return: 0 for success or negative error code
> + */
> +int poweroff_handler_register(struct poweroff_handler *handler)
> +{
> +	if (!handler->name)
> +		handler->name = POWEROFF_DEFAULT_NAME;
> +	if (!handler->priority)
> +		handler->priority = POWEROFF_DEFAULT_PRIORITY;
> +
> +	list_add_tail(&handler->list, &poweroff_handler_list);
> +
> +	pr_debug("registering poweroff handler \"%s\" with priority %d\n",
> +			handler->name, handler->priority);
> +
> +	return 0;
> +}
> +
> +/**
> + * poweroff_handler_register_fn() - register a handler function
> + * @poweroff_fn:	The poweroff function
> + *
> + * convenience wrapper for poweroff_handler_register() to register a handler
> + * with given function and default values otherwise.
> + *
> + * return: 0 for success or negative error code
> + */
> +int poweroff_handler_register_fn(void (*poweroff_fn)(struct poweroff_handler *))
> +{
> +	struct poweroff_handler *handler;
> +	int ret;
> +
> +	handler = xzalloc(sizeof(*handler));
> +
> +	handler->poweroff = poweroff_fn;
> +
> +	ret = poweroff_handler_register(handler);
> +
> +	if (ret)
> +		free(handler);
> +
> +	return ret;
> +}
> +
> +/**
> + * poweroff_machine() - power off the machine
> + */
> +void __noreturn poweroff_machine(void)
> +{
> +	struct poweroff_handler *handler = NULL, *tmp;
> +	unsigned int priority = 0;
> +
> +	list_for_each_entry(tmp, &poweroff_handler_list, list) {
> +		if (tmp->priority > priority) {
> +			priority = tmp->priority;
> +			handler = tmp;
> +		}
> +	}
> +
> +	if (handler) {
> +		pr_debug("using poweroff handler %s\n", handler->name);
> +		console_flush();
> +		handler->poweroff(handler);
> +	} else {
> +		pr_err("No poweroff handler found!\n");
> +	}
> +
> +	hang();
> +}
> +
> +/**
> + * of_get_poweroff_priority() - get the desired poweroff priority from device tree
> + * @node:	The device_node to read the property from
> + *
> + * return: The priority
> + */
> +unsigned int of_get_poweroff_priority(struct device_node *node)
> +{
> +	unsigned int priority = POWEROFF_DEFAULT_PRIORITY;
> +
> +	of_property_read_u32(node, "poweroff-priority", &priority);
> +
> +	return priority;
> +}
> diff --git a/include/common.h b/include/common.h
> index 680a0affb..dd7445e9b 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -66,9 +66,6 @@ int	readline	(const char *prompt, char *buf, int len);
>  /* common/memsize.c */
>  long	get_ram_size  (volatile long *, long);
>  
> -/* $(CPU)/cpu.c */
> -void __noreturn poweroff(void);
> -
>  /* common/console.c */
>  int	ctrlc (void);
>  
> diff --git a/include/poweroff.h b/include/poweroff.h
> new file mode 100644
> index 000000000..ae9557db5
> --- /dev/null
> +++ b/include/poweroff.h
> @@ -0,0 +1,21 @@
> +#ifndef __INCLUDE_POWEROFF_H
> +#define __INCLUDE_POWEROFF_H
> +
> +void __noreturn poweroff_machine(void);
> +
> +struct poweroff_handler {
> +	void (*poweroff)(struct poweroff_handler *);
> +	int priority;
> +	const char *name;
> +	struct list_head list;
> +};
> +
> +int poweroff_handler_register(struct poweroff_handler *);
> +int poweroff_handler_register_fn(void (*poweroff_fn)(struct poweroff_handler *));
> +
> +#define POWEROFF_DEFAULT_PRIORITY 100
> +#define POWEROFF_DEFAULT_NAME "default"
> +
> +unsigned int of_get_poweroff_priority(struct device_node *node);
> +
> +#endif /* __INCLUDE_POWEROFF_H */
> -- 
> 2.11.0
> 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-03-14  7:18 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-13 11:05 [PATCH v2] poweroff: Allow to register poweroff handlers Oleksij Rempel
2017-03-14  7:17 ` Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox