diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2015-09-01 09:43:55 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2015-09-01 09:43:55 +0200 |
commit | 67e0a30e77c0dadfb225eef7e9bdcccdcae4d679 (patch) | |
tree | aa1887ec66dc1e48eaeacca93ac38b55a49a3f99 /common | |
parent | b7ab2081b1f1f13f0823bb6e8e33884510e105d7 (diff) | |
parent | ce36b4a05e275dcc12e74e96ddae99c21faad466 (diff) | |
download | barebox-67e0a30e77c0dadfb225eef7e9bdcccdcae4d679.tar.gz barebox-67e0a30e77c0dadfb225eef7e9bdcccdcae4d679.tar.xz |
Merge branch 'for-next/restart'
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/misc.c | 3 | ||||
-rw-r--r-- | common/reset_source.c | 31 | ||||
-rw-r--r-- | common/restart.c | 112 |
4 files changed, 142 insertions, 5 deletions
diff --git a/common/Makefile b/common/Makefile index ed131c8c56..1e7a08190c 100644 --- a/common/Makefile +++ b/common/Makefile @@ -8,6 +8,7 @@ obj-y += misc.o obj-pbl-y += memsize.o obj-y += resource.o obj-y += bootsource.o +obj-y += restart.o obj-$(CONFIG_AUTO_COMPLETE) += complete.o obj-$(CONFIG_BANNER) += version.o obj-$(CONFIG_BAREBOX_UPDATE) += bbu.o diff --git a/common/misc.c b/common/misc.c index 6da71c7ab7..5532349e43 100644 --- a/common/misc.c +++ b/common/misc.c @@ -24,6 +24,7 @@ #include <environment.h> #include <led.h> #include <of.h> +#include <restart.h> int errno; EXPORT_SYMBOL(errno); @@ -206,7 +207,7 @@ void __noreturn panic(const char *fmt, ...) hang(); } else { udelay(100000); /* allow messages to go out */ - reset_cpu(0); + restart_machine(); } } EXPORT_SYMBOL(panic); diff --git a/common/reset_source.c b/common/reset_source.c index 80002a93e6..0a69f90a6e 100644 --- a/common/reset_source.c +++ b/common/reset_source.c @@ -11,6 +11,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ +#define pr_fmt(fmt) "reset-source: " fmt #include <common.h> #include <init.h> @@ -30,6 +31,7 @@ static const char * const reset_src_names[] = { }; static enum reset_src_type reset_source; +static unsigned int reset_source_priority; enum reset_src_type reset_source_get(void) { @@ -37,20 +39,41 @@ enum reset_src_type reset_source_get(void) } EXPORT_SYMBOL(reset_source_get); -void reset_source_set(enum reset_src_type st) +void reset_source_set_priority(enum reset_src_type st, unsigned int priority) { + if (priority <= reset_source_priority) + return; + reset_source = st; + reset_source_priority = priority; - globalvar_add_simple("system.reset", reset_src_names[reset_source]); + pr_debug("Setting reset source to %s with priority %d\n", + reset_src_names[reset_source], priority); } EXPORT_SYMBOL(reset_source_set); -/* ensure this runs after the 'global' device is already registerd */ static int reset_source_init(void) { - reset_source_set(reset_source); + globalvar_add_simple_enum("system.reset", (unsigned int *)&reset_source, + reset_src_names, ARRAY_SIZE(reset_src_names)); return 0; } coredevice_initcall(reset_source_init); + +/** + * of_get_reset_source_priority() - get the desired reset source priority from + * device tree + * @node: The device_node to read the property from + * + * return: The priority + */ +unsigned int of_get_reset_source_priority(struct device_node *node) +{ + unsigned int priority = RESET_SOURCE_DEFAULT_PRIORITY; + + of_property_read_u32(node, "reset-source-priority", &priority); + + return priority; +} diff --git a/common/restart.c b/common/restart.c new file mode 100644 index 0000000000..8fd5ffd1a2 --- /dev/null +++ b/common/restart.c @@ -0,0 +1,112 @@ +/* + * 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) "restart: " fmt + +#include <common.h> +#include <restart.h> +#include <malloc.h> +#include <of.h> + +static LIST_HEAD(restart_handler_list); + +/** + * restart_handler_register() - register a handler for restarting the system + * @rst: The handler struct + * + * This adds @rst to the list of registered restart handlers. + * + * return: 0 for success or negative error code + */ +int restart_handler_register(struct restart_handler *rst) +{ + if (!rst->name) + rst->name = RESTART_DEFAULT_NAME; + if (!rst->priority) + rst->priority = RESTART_DEFAULT_PRIORITY; + + list_add_tail(&rst->list, &restart_handler_list); + + pr_debug("registering restart handler \"%s\" with priority %d\n", + rst->name, rst->priority); + + return 0; +} + +/** + * restart_handler_register_fn() - register a handler function + * @restart_fn: The restart function + * + * convenience wrapper for restart_handler_register() to register a handler + * with given function and default values otherwise. + * + * return: 0 for success or negative error code + */ +int restart_handler_register_fn(void (*restart_fn)(struct restart_handler *)) +{ + struct restart_handler *rst; + int ret; + + rst = xzalloc(sizeof(*rst)); + + rst->restart = restart_fn; + + ret = restart_handler_register(rst); + + if (ret) + free(rst); + + return ret; +} + +/** + * restart_machine() - reset the whole system + */ +void __noreturn restart_machine(void) +{ + struct restart_handler *rst = NULL, *tmp; + unsigned int priority = 0; + + list_for_each_entry(tmp, &restart_handler_list, list) { + if (tmp->priority > priority) { + priority = tmp->priority; + rst = tmp; + } + } + + if (rst) { + pr_debug("%s: using restart handler %s\n", __func__, rst->name); + console_flush(); + rst->restart(rst); + } + + hang(); +} + +/** + * of_get_restart_priority() - get the desired restart priority from device tree + * @node: The device_node to read the property from + * + * return: The priority + */ +unsigned int of_get_restart_priority(struct device_node *node) +{ + unsigned int priority = RESTART_DEFAULT_PRIORITY; + + of_property_read_u32(node, "restart-priority", &priority); + + return priority; +} |