[PATCH v2] poweroff: Allow to register poweroff handlers
Sascha Hauer
s.hauer at pengutronix.de
Tue Mar 14 00:17:55 PDT 2017
On Mon, Mar 13, 2017 at 12:05:23PM +0100, Oleksij Rempel wrote:
> From: Sascha Hauer <s.hauer at 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 at pengutronix.de>
> Signed-off-by: Oleksij Rempel <o.rempel at 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 at 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 |
More information about the barebox
mailing list