* [PATCH 1/5] Reset reason: add a scope value to the reset reason feature
2015-06-25 7:34 [PATCHv3] Change barebox regarding "machine-restart", "reset cause detection" und "watchdog usage" Juergen Borleis
@ 2015-06-25 7:34 ` Juergen Borleis
2015-06-25 7:34 ` [PATCH 2/5] System restart: add a scope value to the system restart feature Juergen Borleis
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Juergen Borleis @ 2015-06-25 7:34 UTC (permalink / raw)
To: barebox
Some systems do have more than one source to detect the reason of a reset.
In this case it depends on the initialization order which reason will be
reported to barebox. To avoid this race, this change adds a scope to the
function call to always accept settings with a wider scope and ignore
all settings with a limited scope.
This change is required to support systems where one reset reason source
is more reliable than other sources. Examples are all i.MX SoCs with
an internal reset reason detector and an external PMIC which has the same
capabilities. For these systems the external PMIC provides the correct
reset cause while the internal unit flags a POR only all the time. In order
to support one binary for more than one machine we cannot just disable the
internal reset reason detector, so we need this scope mechanism.
Assumption in this change is, the reset cause sources with a wider scope are
always reporting the correct reason and not vice versa.
Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
Documentation/user/reset-reason.rst | 30 ++++++++++++++++++++++++++++
Documentation/user/system-reset.rst | 3 ++-
arch/arm/mach-imx/imx1.c | 8 ++++----
arch/arm/mach-omap/am33xx_generic.c | 14 ++++++-------
arch/arm/mach-pxa/pxa2xx.c | 12 ++++++------
arch/arm/mach-pxa/pxa3xx.c | 12 ++++++------
arch/arm/mach-samsung/reset_source.c | 8 ++++----
arch/arm/mach-tegra/tegra20-pmc.c | 14 ++++++-------
common/Kconfig | 8 --------
common/Makefile | 2 +-
common/{reset_source.c => restart.c} | 37 +++++++++++++++++++++++------------
drivers/watchdog/im28wd.c | 12 ++++++------
drivers/watchdog/imxwd.c | 8 ++++----
include/{reset_source.h => restart.h} | 29 +++++++++++++--------------
14 files changed, 115 insertions(+), 82 deletions(-)
rename common/{reset_source.c => restart.c} (54%)
rename include/{reset_source.h => restart.h} (71%)
diff --git a/Documentation/user/reset-reason.rst b/Documentation/user/reset-reason.rst
index a4872fa..525ade2 100644
--- a/Documentation/user/reset-reason.rst
+++ b/Documentation/user/reset-reason.rst
@@ -3,6 +3,9 @@
Reset Reason
------------
+Using the Reset Reason
+~~~~~~~~~~~~~~~~~~~~~~
+
To handle a device in a secure and safty manner many applications are using
a watchdog or other ways to reset a system to bring it back into life if it
hangs or crashes somehow.
@@ -45,3 +48,30 @@ The following values can help to detect the reason why the bootloader runs:
It depends on your board/SoC and its features if the hardware is able to detect
these reset reasons. Most of the time only ``POR`` and ``RST`` are supported
but often ``WDG`` as well.
+
+.. _reset_reason_scope:
+
+Scope of Reset Reason
+~~~~~~~~~~~~~~~~~~~~~
+
+Some machines can detect the reset reason via different devices, for example
+via a SoC internal devices and an externally attached device. Both can provide
+the correct reason - or not. If their reset reason point of view differ, you
+need a ``scope`` to decide what reason is the correct one. Barebox provides
+the reset reason scope via the global variable ``system.reset.scope`` and
+the following values:
+
+* ``unknown``: the software can't define the scope of the reset reason.
+* ``cpu``: the inner core CPU only point of view.
+* ``soc``: the full SoC point of view.
+* ``machine``: the full machine point of view
+
+The scopes are rated: lowest rate is ``unknown`` and ``cpu``. The highest
+rate has the ``machine`` point of view. The ``soc`` point of view in inbetween.
+
+Why can the reset reason differ due to different scopes? Think about a SoC which
+is powered by a PMIC: the reset reason detection inside the SoC has the ``soc``
+scope, the PMIC's reset reason detection has the ``machine`` scope. In this case
+the ``soc`` scope reset reason is always ``POR``, while the ``machine`` scope
+reset reason is ``POR`` only on a real POR, ``RST`` due to an user
+intervention and ``WDG`` because the system has failed somehow.
diff --git a/Documentation/user/system-reset.rst b/Documentation/user/system-reset.rst
index e76e3a2..e902026 100644
--- a/Documentation/user/system-reset.rst
+++ b/Documentation/user/system-reset.rst
@@ -61,4 +61,5 @@ wide reset, like the POR is.
Drawback of the PMIC solution is, you can't use the SoC's internal mechanisms to
detect the :ref:`reset_reason` anymore. From the SoC point of view it is always
a POR when the PMIC handles the system reset. If you are in luck the PMIC
-instead can provide this information if you depend on it.
+instead can provide this information if you depend on it. Refer
+:ref:`reset_reason_scope` for further information.
diff --git a/arch/arm/mach-imx/imx1.c b/arch/arm/mach-imx/imx1.c
index 51bdcbf..a3759df 100644
--- a/arch/arm/mach-imx/imx1.c
+++ b/arch/arm/mach-imx/imx1.c
@@ -18,7 +18,7 @@
#include <mach/weim.h>
#include <mach/iomux-v1.h>
#include <mach/generic.h>
-#include <reset_source.h>
+#include <restart.h>
#define MX1_RSR MX1_SCM_BASE_ADDR
#define RSR_EXR (1 << 0)
@@ -30,13 +30,13 @@ static void imx1_detect_reset_source(void)
switch (val) {
case RSR_EXR:
- reset_source_set(RESET_RST);
+ reset_source_set(RESET_RST, FEATURE_SCOPE_SOC);
return;
case RSR_WDR:
- reset_source_set(RESET_WDG);
+ reset_source_set(RESET_WDG, FEATURE_SCOPE_SOC);
return;
case 0:
- reset_source_set(RESET_POR);
+ reset_source_set(RESET_POR, FEATURE_SCOPE_SOC);
return;
default:
/* else keep the default 'unknown' state */
diff --git a/arch/arm/mach-omap/am33xx_generic.c b/arch/arm/mach-omap/am33xx_generic.c
index 7ce32f0..8ac1290 100644
--- a/arch/arm/mach-omap/am33xx_generic.c
+++ b/arch/arm/mach-omap/am33xx_generic.c
@@ -26,7 +26,7 @@
#include <mach/sys_info.h>
#include <mach/am33xx-generic.h>
#include <mach/gpmc.h>
-#include <reset_source.h>
+#include <restart.h>
void __noreturn am33xx_reset_cpu(unsigned long addr)
{
@@ -167,23 +167,23 @@ static void am33xx_detect_reset_reason(void)
switch (val) {
case (1 << 9):
- reset_source_set(RESET_JTAG);
+ reset_source_set(RESET_JTAG, FEATURE_SCOPE_SOC);
break;
case (1 << 5):
- reset_source_set(RESET_EXT);
+ reset_source_set(RESET_EXT, FEATURE_SCOPE_SOC);
break;
case (1 << 4):
case (1 << 3):
- reset_source_set(RESET_WDG);
+ reset_source_set(RESET_WDG, FEATURE_SCOPE_SOC);
break;
case (1 << 1):
- reset_source_set(RESET_RST);
+ reset_source_set(RESET_RST, FEATURE_SCOPE_SOC);
break;
case (1 << 0):
- reset_source_set(RESET_POR);
+ reset_source_set(RESET_POR, FEATURE_SCOPE_SOC);
break;
default:
- reset_source_set(RESET_UKWN);
+ reset_source_set(RESET_UKWN, FEATURE_SCOPE_SOC);
break;
}
}
diff --git a/arch/arm/mach-pxa/pxa2xx.c b/arch/arm/mach-pxa/pxa2xx.c
index b712b38..973e394 100644
--- a/arch/arm/mach-pxa/pxa2xx.c
+++ b/arch/arm/mach-pxa/pxa2xx.c
@@ -14,7 +14,7 @@
#include <common.h>
#include <init.h>
-#include <reset_source.h>
+#include <restart.h>
#include <mach/hardware.h>
#include <mach/pxa-regs.h>
@@ -28,15 +28,15 @@ static int pxa_detect_reset_source(void)
* Order is important, as many bits can be set together
*/
if (reg & RCSR_GPR)
- reset_source_set(RESET_RST);
+ reset_source_set(RESET_RST, FEATURE_SCOPE_SOC);
else if (reg & RCSR_WDR)
- reset_source_set(RESET_WDG);
+ reset_source_set(RESET_WDG, FEATURE_SCOPE_SOC);
else if (reg & RCSR_HWR)
- reset_source_set(RESET_POR);
+ reset_source_set(RESET_POR, FEATURE_SCOPE_SOC);
else if (reg & RCSR_SMR)
- reset_source_set(RESET_WKE);
+ reset_source_set(RESET_WKE, FEATURE_SCOPE_SOC);
else
- reset_source_set(RESET_UKWN);
+ reset_source_set(RESET_UKWN, FEATURE_SCOPE_SOC);
return 0;
}
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 86ca63b..e273996 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -14,7 +14,7 @@
#include <common.h>
#include <init.h>
-#include <reset_source.h>
+#include <restart.h>
#include <mach/hardware.h>
#include <mach/pxa-regs.h>
@@ -28,15 +28,15 @@ static int pxa_detect_reset_source(void)
* Order is important, as many bits can be set together
*/
if (reg & ARSR_GPR)
- reset_source_set(RESET_RST);
+ reset_source_set(RESET_RST, FEATURE_SCOPE_SOC);
else if (reg & ARSR_WDT)
- reset_source_set(RESET_WDG);
+ reset_source_set(RESET_WDG, FEATURE_SCOPE_SOC);
else if (reg & ARSR_HWR)
- reset_source_set(RESET_POR);
+ reset_source_set(RESET_POR, FEATURE_SCOPE_SOC);
else if (reg & ARSR_LPMR)
- reset_source_set(RESET_WKE);
+ reset_source_set(RESET_WKE, FEATURE_SCOPE_SOC);
else
- reset_source_set(RESET_UKWN);
+ reset_source_set(RESET_UKWN, FEATURE_SCOPE_SOC);
return 0;
}
diff --git a/arch/arm/mach-samsung/reset_source.c b/arch/arm/mach-samsung/reset_source.c
index c1365b2..e122909 100644
--- a/arch/arm/mach-samsung/reset_source.c
+++ b/arch/arm/mach-samsung/reset_source.c
@@ -15,7 +15,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
-#include <reset_source.h>
+#include <restart.h>
#include <mach/s3c-iomap.h>
/* S3C2440 relevant */
@@ -29,21 +29,21 @@ static int s3c_detect_reset_source(void)
u32 reg = readl(S3C_GPIO_BASE + S3C2440_GSTATUS2);
if (reg & S3C2440_GSTATUS2_PWRST) {
- reset_source_set(RESET_POR);
+ reset_source_set(RESET_POR, FEATURE_SCOPE_SOC);
writel(S3C2440_GSTATUS2_PWRST,
S3C_GPIO_BASE + S3C2440_GSTATUS2);
return 0;
}
if (reg & S3C2440_GSTATUS2_SLEEPRST) {
- reset_source_set(RESET_WKE);
+ reset_source_set(RESET_WKE, FEATURE_SCOPE_SOC);
writel(S3C2440_GSTATUS2_SLEEPRST,
S3C_GPIO_BASE + S3C2440_GSTATUS2);
return 0;
}
if (reg & S3C2440_GSTATUS2_WDRST) {
- reset_source_set(RESET_WDG);
+ reset_source_set(RESET_WDG, FEATURE_SCOPE_SOC);
writel(S3C2440_GSTATUS2_WDRST,
S3C_GPIO_BASE + S3C2440_GSTATUS2);
return 0;
diff --git a/arch/arm/mach-tegra/tegra20-pmc.c b/arch/arm/mach-tegra/tegra20-pmc.c
index eaa5ac7..6493eea 100644
--- a/arch/arm/mach-tegra/tegra20-pmc.c
+++ b/arch/arm/mach-tegra/tegra20-pmc.c
@@ -28,7 +28,7 @@
#include <linux/reset.h>
#include <mach/lowlevel.h>
#include <mach/tegra-powergate.h>
-#include <reset_source.h>
+#include <restart.h>
#include <mach/tegra20-pmc.h>
@@ -180,22 +180,22 @@ static void tegra20_pmc_detect_reset_cause(void)
switch ((reg & PMC_RST_STATUS_RST_SRC_MASK) >>
PMC_RST_STATUS_RST_SRC_SHIFT) {
case PMC_RST_STATUS_RST_SRC_POR:
- reset_source_set(RESET_POR);
+ reset_source_set(RESET_POR, FEATURE_SCOPE_SOC);
break;
case PMC_RST_STATUS_RST_SRC_WATCHDOG:
- reset_source_set(RESET_WDG);
+ reset_source_set(RESET_WDG, FEATURE_SCOPE_SOC);
break;
case PMC_RST_STATUS_RST_SRC_LP0:
- reset_source_set(RESET_WKE);
+ reset_source_set(RESET_WKE, FEATURE_SCOPE_SOC);
break;
case PMC_RST_STATUS_RST_SRC_SW_MAIN:
- reset_source_set(RESET_RST);
+ reset_source_set(RESET_RST, FEATURE_SCOPE_SOC);
break;
case PMC_RST_STATUS_RST_SRC_SENSOR:
- reset_source_set(RESET_THERM);
+ reset_source_set(RESET_THERM, FEATURE_SCOPE_SOC);
break;
default:
- reset_source_set(RESET_UKWN);
+ reset_source_set(RESET_UKWN, FEATURE_SCOPE_SOC);
break;
}
}
diff --git a/common/Kconfig b/common/Kconfig
index 3dfb5ac..f241482 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -716,14 +716,6 @@ config STATE
select OFTREE
select PARAMETER
-config RESET_SOURCE
- bool "detect Reset cause"
- depends on GLOBALVAR
- help
- Provide a global variable at runtine which reflects the possible cause
- of the reset and why the bootloader is currently running. It can be
- useful for any kind of system recovery or repair.
-
endmenu
menu "Debugging"
diff --git a/common/Makefile b/common/Makefile
index 2738238..16e6690 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -8,6 +8,7 @@ obj-y += misc.o
obj-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
@@ -40,7 +41,6 @@ obj-$(CONFIG_OFTREE) += oftree.o
obj-$(CONFIG_PARTITION_DISK) += partitions.o partitions/
obj-$(CONFIG_PASSWORD) += password.o
obj-$(CONFIG_POLLER) += poller.o
-obj-$(CONFIG_RESET_SOURCE) += reset_source.o
obj-$(CONFIG_SHELL_HUSH) += hush.o
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
obj-$(CONFIG_STATE) += state.o
diff --git a/common/reset_source.c b/common/restart.c
similarity index 54%
rename from common/reset_source.c
rename to common/restart.c
index 80002a9..5b53264 100644
--- a/common/reset_source.c
+++ b/common/restart.c
@@ -1,5 +1,5 @@
/*
- * (C) Copyright 2012 Juergen Beisert - <kernel@pengutronix.de>
+ * (C) Copyright 2015 Juergen Borleis - <kernel@pengutronix.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -14,9 +14,15 @@
#include <common.h>
#include <init.h>
-#include <environment.h>
+#include <restart.h>
#include <globalvar.h>
-#include <reset_source.h>
+
+static const char * const scope_names[] = {
+ [FEATURE_SCOPE_UNKNOWN] = "unknown",
+ [FEATURE_SCOPE_CPU] = "cpu",
+ [FEATURE_SCOPE_SOC] = "soc",
+ [FEATURE_SCOPE_MACHINE] = "machine",
+};
static const char * const reset_src_names[] = {
[RESET_UKWN] = "unknown",
@@ -29,7 +35,10 @@ static const char * const reset_src_names[] = {
[RESET_EXT] = "EXT",
};
-static enum reset_src_type reset_source;
+/* handle reset cause detection feature */
+
+static int reset_source;
+static int reset_source_scope;
enum reset_src_type reset_source_get(void)
{
@@ -37,20 +46,22 @@ 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(enum reset_src_type st, enum f_scope scope)
{
- reset_source = st;
+ if (scope <= reset_source_scope)
+ return; /* just ignore this setting */
- globalvar_add_simple("system.reset", reset_src_names[reset_source]);
+ reset_source = st;
+ reset_source_scope = scope;
}
EXPORT_SYMBOL(reset_source_set);
-/* ensure this runs after the 'global' device is already registerd */
-static int reset_source_init(void)
+static int reset_feature_init(void)
{
- reset_source_set(reset_source);
-
+ globalvar_add_simple_enum("system.reset", &reset_source, reset_src_names,
+ ARRAY_SIZE(reset_src_names));
+ globalvar_add_simple_enum("system.reset.scope", &reset_source_scope,
+ scope_names, ARRAY_SIZE(scope_names));
return 0;
}
-
-coredevice_initcall(reset_source_init);
+coredevice_initcall(reset_feature_init);
diff --git a/drivers/watchdog/im28wd.c b/drivers/watchdog/im28wd.c
index a9093a7..c824a25 100644
--- a/drivers/watchdog/im28wd.c
+++ b/drivers/watchdog/im28wd.c
@@ -21,7 +21,7 @@
#include <errno.h>
#include <malloc.h>
#include <watchdog.h>
-#include <reset_source.h>
+#include <restart.h>
#include <linux/err.h>
#define MXS_RTC_CTRL 0x0
@@ -164,27 +164,27 @@ static void __maybe_unused imx28_detect_reset_source(const struct imx28_wd *p)
if (reg & MXS_RTC_PERSISTENT0_ALARM_WAKE) {
writel(MXS_RTC_PERSISTENT0_ALARM_WAKE,
p->regs + MXS_RTC_PERSISTENT0 + MXS_RTC_CLR_ADDR);
- reset_source_set(RESET_WKE);
+ reset_source_set(RESET_WKE, FEATURE_SCOPE_SOC);
return;
}
- reset_source_set(RESET_POR);
+ reset_source_set(RESET_POR, FEATURE_SCOPE_SOC);
return;
}
if (reg & MXS_RTC_PERSISTENT0_THM_RST) {
writel(MXS_RTC_PERSISTENT0_THM_RST,
p->regs + MXS_RTC_PERSISTENT0 + MXS_RTC_CLR_ADDR);
- reset_source_set(RESET_RST);
+ reset_source_set(RESET_RST, FEATURE_SCOPE_SOC);
return;
}
reg = readl(p->regs + MXS_RTC_PERSISTENT1);
if (reg & MXS_RTC_PERSISTENT1_FORCE_UPDATER) {
writel(MXS_RTC_PERSISTENT1_FORCE_UPDATER,
p->regs + MXS_RTC_PERSISTENT1 + MXS_RTC_CLR_ADDR);
- reset_source_set(RESET_WDG);
+ reset_source_set(RESET_WDG, FEATURE_SCOPE_SOC);
return;
}
- reset_source_set(RESET_RST);
+ reset_source_set(RESET_RST, FEATURE_SCOPE_SOC);
}
static int imx28_wd_probe(struct device_d *dev)
diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
index 5ffbac7..f3decae 100644
--- a/drivers/watchdog/imxwd.c
+++ b/drivers/watchdog/imxwd.c
@@ -19,7 +19,7 @@
#include <errno.h>
#include <malloc.h>
#include <watchdog.h>
-#include <reset_source.h>
+#include <restart.h>
struct imx_wd;
@@ -138,17 +138,17 @@ static void imx_watchdog_detect_reset_source(struct imx_wd *priv)
u16 val = readw(priv->base + IMX21_WDOG_WSTR);
if (val & WSTR_COLDSTART) {
- reset_source_set(RESET_POR);
+ reset_source_set(RESET_POR, FEATURE_SCOPE_SOC);
return;
}
if (val & (WSTR_HARDRESET | WSTR_WARMSTART)) {
- reset_source_set(RESET_RST);
+ reset_source_set(RESET_RST, FEATURE_SCOPE_SOC);
return;
}
if (val & WSTR_WDOG) {
- reset_source_set(RESET_WDG);
+ reset_source_set(RESET_WDG, FEATURE_SCOPE_SOC);
return;
}
diff --git a/include/reset_source.h b/include/restart.h
similarity index 71%
rename from include/reset_source.h
rename to include/restart.h
index 367f93b..4215760 100644
--- a/include/reset_source.h
+++ b/include/restart.h
@@ -10,8 +10,18 @@
* GNU General Public License for more details.
*/
-#ifndef __INCLUDE_RESET_SOURCE_H
-# define __INCLUDE_RESET_SOURCE_H
+#ifndef __INCLUDE_SYSTEM_RESTART_H
+# define __INCLUDE_SYSTEM_RESTART_H
+
+/* define a scope a specific hardware feature can cope with */
+enum f_scope {
+ FEATURE_SCOPE_UNKNOWN,
+ FEATURE_SCOPE_CPU,
+ FEATURE_SCOPE_SOC,
+ FEATURE_SCOPE_MACHINE,
+};
+
+/* reset cause detection feature */
enum reset_src_type {
RESET_UKWN, /* maybe the SoC cannot detect the reset source */
@@ -24,18 +34,7 @@ enum reset_src_type {
RESET_EXT, /* External reset through device pin */
};
-#ifdef CONFIG_RESET_SOURCE
-void reset_source_set(enum reset_src_type);
+void reset_source_set(enum reset_src_type, enum f_scope);
enum reset_src_type reset_source_get(void);
-#else
-static inline void reset_source_set(enum reset_src_type unused)
-{
-}
-
-static inline enum reset_src_type reset_source_get(void)
-{
- return RESET_UKWN;
-}
-#endif
-#endif /* __INCLUDE_RESET_SOURCE_H */
+#endif /* __INCLUDE_SYSTEM_RESTART_H */
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/5] System restart: add a scope value to the system restart feature
2015-06-25 7:34 [PATCHv3] Change barebox regarding "machine-restart", "reset cause detection" und "watchdog usage" Juergen Borleis
2015-06-25 7:34 ` [PATCH 1/5] Reset reason: add a scope value to the reset reason feature Juergen Borleis
@ 2015-06-25 7:34 ` Juergen Borleis
2015-06-25 7:34 ` [PATCH 3/5] Watchdog: add a scope value to the watchdog feature Juergen Borleis
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Juergen Borleis @ 2015-06-25 7:34 UTC (permalink / raw)
To: barebox
Some systems have more than one feature to restart it. Maybe these restarts
features are all equal or it is very important which restart feauture is used
to restart the system in a reliable manner. For example if external
devices must be reset in conjunction with the SoC some SoC's internal
restart features cannot be used. Then an external restart feature must
be forced instead by using the restart feature with the wider scope.
Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
Documentation/user/system-reset.rst | 41 ++++++++++++++++++
arch/arm/lib/bootm.c | 7 ++--
arch/arm/mach-at91/at91rm9200_time.c | 12 ++++--
arch/arm/mach-at91/at91sam9_reset.S | 4 +-
arch/arm/mach-at91/at91sam9g45_reset.S | 4 +-
arch/arm/mach-at91/bootstrap.c | 2 +-
arch/arm/mach-at91/setup.c | 9 ++++
arch/arm/mach-bcm2835/core.c | 21 +++++-----
arch/arm/mach-clps711x/reset.c | 10 ++++-
arch/arm/mach-davinci/time.c | 12 ++++--
arch/arm/mach-digic/core.c | 25 -----------
arch/arm/mach-ep93xx/clocksource.c | 17 ++++----
arch/arm/mach-highbank/reset.c | 12 +++++-
arch/arm/mach-mvebu/armada-370-xp.c | 9 ++--
arch/arm/mach-mvebu/common.c | 13 ------
arch/arm/mach-mvebu/dove.c | 9 ++--
arch/arm/mach-mvebu/include/mach/common.h | 1 -
arch/arm/mach-mvebu/kirkwood.c | 9 ++--
arch/arm/mach-mxs/soc-imx23.c | 8 ++--
arch/arm/mach-mxs/soc-imx28.c | 13 ++++--
arch/arm/mach-netx/generic.c | 11 ++++-
arch/arm/mach-nomadik/reset.c | 13 ++++--
arch/arm/mach-omap/am33xx_generic.c | 4 +-
arch/arm/mach-omap/include/mach/am33xx-generic.h | 2 +-
arch/arm/mach-omap/include/mach/omap3-generic.h | 2 +-
arch/arm/mach-omap/include/mach/omap4-generic.h | 2 +-
arch/arm/mach-omap/omap3_generic.c | 5 +--
arch/arm/mach-omap/omap4_generic.c | 4 +-
arch/arm/mach-omap/omap_generic.c | 12 +++---
arch/arm/mach-pxa/common.c | 12 +++++-
arch/arm/mach-rockchip/core.c | 14 +++++--
arch/arm/mach-samsung/generic.c | 13 ++++--
arch/arm/mach-socfpga/reset-manager.c | 12 +++++-
arch/arm/mach-tegra/tegra20-pmc.c | 8 ++--
arch/arm/mach-uemd/reset.c | 24 -----------
arch/arm/mach-versatile/core.c | 7 ++--
arch/arm/mach-vexpress/reset.c | 13 ++++--
arch/arm/mach-zynq/zynq.c | 12 ++++--
arch/blackfin/lib/cpu.c | 11 ++++-
arch/blackfin/lib/traps.c | 4 +-
arch/efi/efi/efi.c | 11 ++++-
arch/mips/lib/bootm.c | 2 +-
arch/mips/mach-ar231x/ar231x_reset.c | 8 ++--
arch/mips/mach-ath79/reset.c | 13 ++++--
arch/mips/mach-bcm47xx/reset.c | 14 +++++--
arch/mips/mach-loongson/loongson1_reset.c | 13 ++++--
arch/mips/mach-malta/reset.c | 14 +++++--
arch/nios2/cpu/cpu.c | 12 +++++-
arch/openrisc/cpu/cpu.c | 11 ++++-
arch/ppc/lib/ppclinux.c | 2 +-
arch/ppc/mach-mpc5xxx/cpu.c | 11 ++++-
arch/ppc/mach-mpc85xx/cpu.c | 12 ++++--
arch/sandbox/os/common.c | 14 +++++--
arch/x86/mach-i386/reset.c | 30 --------------
commands/reset.c | 3 +-
common/misc.c | 3 +-
common/restart.c | 53 ++++++++++++++++++++++++
drivers/usb/gadget/f_fastboot.c | 3 +-
drivers/watchdog/imxwd.c | 21 ++++------
drivers/watchdog/jz4740.c | 33 +++++++--------
include/common.h | 1 -
include/restart.h | 6 +++
62 files changed, 451 insertions(+), 262 deletions(-)
delete mode 100644 arch/arm/mach-digic/core.c
delete mode 100644 arch/arm/mach-uemd/reset.c
delete mode 100644 arch/x86/mach-i386/reset.c
diff --git a/Documentation/user/system-reset.rst b/Documentation/user/system-reset.rst
index e902026..6770371 100644
--- a/Documentation/user/system-reset.rst
+++ b/Documentation/user/system-reset.rst
@@ -3,6 +3,11 @@
System Restart
--------------
+.. _system_reset_pitfalls:
+
+Common Pitfalls
+~~~~~~~~~~~~~~~
+
When running the reset command barebox restarts the SoC somehow. Restart can
be done in software, but a more reliable way is to use a hard reset line, which
really resets the whole machine.
@@ -63,3 +68,39 @@ detect the :ref:`reset_reason` anymore. From the SoC point of view it is always
a POR when the PMIC handles the system reset. If you are in luck the PMIC
instead can provide this information if you depend on it. Refer
:ref:`reset_reason_scope` for further information.
+
+Handling the system restart from the developers point of view
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes more than one system restart feature is available on a machine and
+due to 'some reasons' all these unit's drivers must be enabled at run-time
+(maybe they are MFDs (e.g. multi function devices) or you want to run one
+binary barebox on more than one machine). In such a case more than one driver
+registers its system reset feature at run-time. So a mechanism is required
+in order to let barebox selects the 'correct' one to trigger a system restart.
+
+Barebox can handle and use one system restart feature only. If the available
+system restart features are equivalent it doesn't matter which one barebox
+selects to trigger a system restart. But if your machine depends on a specific
+system restart feature you must ensure it will be used all the time to get a
+reliable system restart.
+
+To handle this, registering system restart features are handled by their scope.
+Due to the listed issues in :ref:`system_reset_pitfalls` all the (mostly) built-in
+watchdog units will register their system restart feature with a limited scope.
+And will still be used by barebox to restart the system if no alternative is
+available.
+If your machine has special requirements to restart the system and a more reliable
+system restart feature is on hand it must register its system restart feature
+with a wider scope. Barebox will then prefer the wider scope feature to restart
+the system.
+
+Here the list of defined scopes (defined in file ``include/restart.h``):
+
+* ``FEATURE_SCOPE_UNKNOWN``: last resort to restart a machine and might be used
+ as a fall-back only.
+* ``FEATURE_SCOPE_CPU``: this restart feature is able to restart the core CPU only.
+* ``FEATURE_SCOPE_SOC``: this restart feature is able to restart the whole SoC,
+ including the core CPU.
+* ``FEATURE_SCOPE_MACHINE``: this restart feature is able to restart the whole machine,
+ including the SoC and the core CPU.
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 8327c3f..7bb9b43 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -16,6 +16,7 @@
#include <libbb.h>
#include <magicvar.h>
#include <binfmt.h>
+#include <restart.h>
#include <asm/byteorder.h>
#include <asm/setup.h>
@@ -111,7 +112,7 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem, int
start_linux((void *)kernel, swap, initrd_start, initrd_size, data->oftree);
- reset_cpu(0);
+ restart_machine();
return -ERESTARTSYS;
}
@@ -378,7 +379,7 @@ static int do_bootm_barebox(struct image_data *data)
start_linux(barebox, 0, 0, 0, data->oftree);
- reset_cpu(0);
+ restart_machine();
}
static struct image_handler barebox_handler = {
@@ -518,7 +519,7 @@ static int do_bootm_aimage(struct image_data *data)
second();
- reset_cpu(0);
+ restart_machine();
}
close(fd);
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index ae0172b..c017ad8 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -28,6 +28,7 @@
#include <common.h>
#include <init.h>
#include <clock.h>
+#include <restart.h>
#include <mach/hardware.h>
#include <mach/at91_tc.h>
#include <mach/at91_st.h>
@@ -77,7 +78,7 @@ core_initcall(clocksource_init);
/*
* Reset the cpu through the reset controller
*/
-void __noreturn reset_cpu (unsigned long ignored)
+static void __noreturn at91rm9200_restart_soc(struct device_d *dev)
{
/*
* Perform a hardware reset with the use of the Watchdog timer.
@@ -86,6 +87,11 @@ void __noreturn reset_cpu (unsigned long ignored)
at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
/* Not reached */
- while (1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(at91rm9200_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-at91/at91sam9_reset.S b/arch/arm/mach-at91/at91sam9_reset.S
index 3a3e77a..890545e 100644
--- a/arch/arm/mach-at91/at91sam9_reset.S
+++ b/arch/arm/mach-at91/at91sam9_reset.S
@@ -20,9 +20,9 @@
.arm
- .globl reset_cpu
+ .globl restart_sam9
-reset_cpu: ldr r0, .at91_va_base_sdramc @ preload constants
+restart_sam9: ldr r0, .at91_va_base_sdramc @ preload constants
ldr r1, .at91_va_base_rstc_cr
mov r2, #1
diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S
index e70d733..2cb113c 100644
--- a/arch/arm/mach-at91/at91sam9g45_reset.S
+++ b/arch/arm/mach-at91/at91sam9g45_reset.S
@@ -17,9 +17,9 @@
.arm
- .globl reset_cpu
+ .globl restart_sam9g45
-reset_cpu: ldr r0, .at91_va_base_sdramc @ preload constants
+restart_sam9g45: ldr r0, .at91_va_base_sdramc @ preload constants
ldr r1, .at91_va_base_rstc_cr
mov r2, #1
diff --git a/arch/arm/mach-at91/bootstrap.c b/arch/arm/mach-at91/bootstrap.c
index 2d18dd6..afd4f1d 100644
--- a/arch/arm/mach-at91/bootstrap.c
+++ b/arch/arm/mach-at91/bootstrap.c
@@ -145,7 +145,7 @@ static void boot_mmc_disk_action(struct menu *m, struct menu_entry *me)
static void boot_reset_action(struct menu *m, struct menu_entry *me)
{
- reset_cpu(0);
+ restart_machine();
}
void at91_bootstrap_menu(void)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 341979a..faaf39b 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <io.h>
#include <init.h>
+#include <restart.h>
#include <mach/hardware.h>
#include <mach/cpu.h>
@@ -296,6 +297,9 @@ static int at91_detect(void)
}
postcore_initcall(at91_detect);
+void restart_sam9(struct device_d*);
+void restart_sam9g45(struct device_d*);
+
static int at91_soc_device(void)
{
struct device_d *dev;
@@ -304,6 +308,11 @@ static int at91_soc_device(void)
dev_add_param_fixed(dev, "name", (char*)at91_get_soc_type(&at91_soc_initdata));
dev_add_param_fixed(dev, "subname", (char*)at91_get_soc_subtype(&at91_soc_initdata));
+ if (IS_ENABLED(CONFIG_AT91SAM9_RESET))
+ restart_register_handler(restart_sam9, NULL, FEATURE_SCOPE_SOC);
+ if (IS_ENABLED(CONFIG_AT91SAM9G45_RESET))
+ restart_register_handler(restart_sam9g45, NULL, FEATURE_SCOPE_SOC);
+
return 0;
}
coredevice_initcall(at91_soc_device);
diff --git a/arch/arm/mach-bcm2835/core.c b/arch/arm/mach-bcm2835/core.c
index 5d08012..6f6ae8a 100644
--- a/arch/arm/mach-bcm2835/core.c
+++ b/arch/arm/mach-bcm2835/core.c
@@ -18,6 +18,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
@@ -51,13 +52,6 @@ static int bcm2835_clk_init(void)
}
postcore_initcall(bcm2835_clk_init);
-static int bcm2835_dev_init(void)
-{
- add_generic_device("bcm2835-gpio", 0, NULL, BCM2835_GPIO_BASE, 0xB0, IORESOURCE_MEM, NULL);
- return 0;
-}
-coredevice_initcall(bcm2835_dev_init);
-
void bcm2835_register_uart(void)
{
amba_apb_device_add(NULL, "uart0-pl011", 0, BCM2835_UART0_BASE, 4096, NULL, 0);
@@ -72,7 +66,7 @@ void bcm2835_add_device_sdram(u32 size)
}
#define RESET_TIMEOUT 10
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn bcm2835_restart_soc(struct device_d *dev)
{
uint32_t rstc;
@@ -82,6 +76,13 @@ void __noreturn reset_cpu(unsigned long addr)
writel(PM_PASSWORD | RESET_TIMEOUT, PM_WDOG);
writel(PM_PASSWORD | rstc, PM_RSTC);
- while (1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int bcm2835_dev_init(void)
+{
+ add_generic_device("bcm2835-gpio", 0, NULL, BCM2835_GPIO_BASE, 0xB0, IORESOURCE_MEM, NULL);
+ restart_register_handler(bcm2835_restart_soc, NULL, FEATURE_SCOPE_SOC);
+ return 0;
+}
+coredevice_initcall(bcm2835_dev_init);
diff --git a/arch/arm/mach-clps711x/reset.c b/arch/arm/mach-clps711x/reset.c
index 67c9c8b..225ef15 100644
--- a/arch/arm/mach-clps711x/reset.c
+++ b/arch/arm/mach-clps711x/reset.c
@@ -8,8 +8,10 @@
*/
#include <common.h>
+#include <init.h>
+#include <restart.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn clps711x_restart_soc(struct device_d *dev)
{
arch_shutdown();
@@ -17,3 +19,9 @@ void __noreturn reset_cpu(unsigned long addr)
hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(clps711x_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 60f0d19..8b53879 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -12,6 +12,7 @@
#include <common.h>
#include <io.h>
#include <init.h>
+#include <restart.h>
#include <clock.h>
#include <mach/time.h>
@@ -164,7 +165,7 @@ static int clocksource_init(void)
core_initcall(clocksource_init);
/* reset board using watchdog timer */
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn davinci_restart_soc(struct device_d *dev)
{
u32 tgcr, wdtcr;
void __iomem *base;
@@ -204,6 +205,11 @@ void __noreturn reset_cpu(ulong addr)
wdtcr = 0x00004000;
__raw_writel(wdtcr, base + WDTCR);
- unreachable();
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(davinci_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-digic/core.c b/arch/arm/mach-digic/core.c
deleted file mode 100644
index b1caec0..0000000
--- a/arch/arm/mach-digic/core.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * This file is part of barebox.
- * 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.
- *
- */
-
-#include <common.h>
-
-void __noreturn reset_cpu(unsigned long ignored)
-{
- pr_err("%s: unimplemented\n", __func__);
- hang();
-}
-EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-ep93xx/clocksource.c b/arch/arm/mach-ep93xx/clocksource.c
index f396d0a..c811641 100644
--- a/arch/arm/mach-ep93xx/clocksource.c
+++ b/arch/arm/mach-ep93xx/clocksource.c
@@ -20,6 +20,7 @@
#include <init.h>
#include <clock.h>
#include <io.h>
+#include <restart.h>
#include <mach/ep93xx-regs.h>
#define TIMER_CLKSEL (1 << 3)
@@ -63,10 +64,8 @@ static int clocksource_init(void)
core_initcall(clocksource_init);
-/*
- * Reset the cpu
- */
-void __noreturn reset_cpu(unsigned long addr)
+/* Reset the SoC */
+static void __noreturn ep92xx_restart_soc(struct device_d *dev)
{
struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
uint32_t value;
@@ -84,7 +83,11 @@ void __noreturn reset_cpu(unsigned long addr)
writel(value, &syscon->devicecfg);
/* Dying... */
- while (1)
- ; /* noop */
+ hang();
+}
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(ep92xx_restart_soc, NULL, FEATURE_SCOPE_SOC);
}
-EXPORT_SYMBOL(reset_cpu);
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-highbank/reset.c b/arch/arm/mach-highbank/reset.c
index b9664e4..cff5cae 100644
--- a/arch/arm/mach-highbank/reset.c
+++ b/arch/arm/mach-highbank/reset.c
@@ -6,17 +6,25 @@
#include <common.h>
#include <io.h>
+#include <restart.h>
+#include <init.h>
#include <mach/devices.h>
#include <mach/sysregs.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn highbank_restart_soc(struct device_d *dev)
{
hingbank_set_pwr_hard_reset();
asm(" wfi");
- while(1);
+ hang();
+}
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(highbank_restart_soc, NULL, FEATURE_SCOPE_SOC);
}
+coredevice_initcall(restart_register_feature);
void __noreturn poweroff()
{
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index 2405629..0c52523 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -17,6 +17,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <of.h>
#include <of_address.h>
#include <asm/memory.h>
@@ -104,12 +105,12 @@ static int armada_370_xp_soc_id_fixup(void)
return 0;
}
-static void __noreturn armada_370_xp_reset_cpu(unsigned long addr)
+static void __noreturn armada_370_xp_restart_soc(struct device_d *dev)
{
writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x60);
writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x64);
- while (1)
- ;
+
+ hang();
}
static int armada_xp_init_soc(struct device_node *root)
@@ -132,7 +133,7 @@ static int armada_370_xp_init_soc(struct device_node *root, void *context)
if (!of_machine_is_compatible("marvell,armada-370-xp"))
return 0;
- mvebu_set_reset(armada_370_xp_reset_cpu);
+ restart_register_handler(armada_370_xp_restart_soc, NULL, FEATURE_SCOPE_SOC);
barebox_set_model("Marvell Armada 370/XP");
barebox_set_hostname("armada");
diff --git a/arch/arm/mach-mvebu/common.c b/arch/arm/mach-mvebu/common.c
index 7d28d9c..cb40d0c 100644
--- a/arch/arm/mach-mvebu/common.c
+++ b/arch/arm/mach-mvebu/common.c
@@ -123,16 +123,3 @@ int mvebu_set_memory(u64 phys_base, u64 phys_size)
return 0;
}
-
-static __noreturn void (*mvebu_reset_cpu)(unsigned long addr);
-
-void __noreturn reset_cpu(unsigned long addr)
-{
- mvebu_reset_cpu(addr);
-}
-EXPORT_SYMBOL(reset_cpu);
-
-void mvebu_set_reset(void __noreturn (*reset)(unsigned long addr))
-{
- mvebu_reset_cpu = reset;
-}
diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c
index a7284fd..b727215 100644
--- a/arch/arm/mach-mvebu/dove.c
+++ b/arch/arm/mach-mvebu/dove.c
@@ -17,6 +17,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <asm/memory.h>
#include <linux/mbus.h>
#include <mach/dove-regs.h>
@@ -68,13 +69,13 @@ static inline void dove_memory_find(unsigned long *phys_base,
}
}
-static void __noreturn dove_reset_cpu(unsigned long addr)
+static void __noreturn dove_restart_soc(struct device_d *dev)
{
/* enable and assert RSTOUTn */
writel(SOFT_RESET_OUT_EN, DOVE_BRIDGE_BASE + BRIDGE_RSTOUT_MASK);
writel(SOFT_RESET_EN, DOVE_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET);
- while (1)
- ;
+
+ hang();
}
static int dove_init_soc(struct device_node *root, void *context)
@@ -84,7 +85,7 @@ static int dove_init_soc(struct device_node *root, void *context)
if (!of_machine_is_compatible("marvell,dove"))
return 0;
- mvebu_set_reset(dove_reset_cpu);
+ restart_register_handler(dove_restart_soc, NULL, FEATURE_SCOPE_SOC);
barebox_set_model("Marvell Dove");
barebox_set_hostname("dove");
diff --git a/arch/arm/mach-mvebu/include/mach/common.h b/arch/arm/mach-mvebu/include/mach/common.h
index 5ce33fd..602af8f 100644
--- a/arch/arm/mach-mvebu/include/mach/common.h
+++ b/arch/arm/mach-mvebu/include/mach/common.h
@@ -21,6 +21,5 @@
#define MVEBU_REMAP_INT_REG_BASE 0xf1000000
int mvebu_set_memory(u64 phys_base, u64 phys_size);
-void mvebu_set_reset(void __noreturn (*reset)(unsigned long addr));
#endif
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c
index 19c6f07..00e213f 100644
--- a/arch/arm/mach-mvebu/kirkwood.c
+++ b/arch/arm/mach-mvebu/kirkwood.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <asm/memory.h>
#include <linux/mbus.h>
#include <mach/kirkwood-regs.h>
@@ -43,12 +44,12 @@ static inline void kirkwood_memory_find(unsigned long *phys_base,
}
}
-static void __noreturn kirkwood_reset_cpu(unsigned long addr)
+static void __noreturn kirkwood_restart_soc(struct device_d *dev)
{
writel(SOFT_RESET_OUT_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_RSTOUT_MASK);
writel(SOFT_RESET_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET);
- for(;;)
- ;
+
+ hang();
}
static int kirkwood_init_soc(struct device_node *root, void *context)
@@ -58,7 +59,7 @@ static int kirkwood_init_soc(struct device_node *root, void *context)
if (!of_machine_is_compatible("marvell,kirkwood"))
return 0;
- mvebu_set_reset(kirkwood_reset_cpu);
+ restart_register_handler(kirkwood_restart_soc, NULL, FEATURE_SCOPE_SOC);
barebox_set_model("Marvell Kirkwood");
barebox_set_hostname("kirkwood");
diff --git a/arch/arm/mach-mxs/soc-imx23.c b/arch/arm/mach-mxs/soc-imx23.c
index 339c577..fd8cf04 100644
--- a/arch/arm/mach-mxs/soc-imx23.c
+++ b/arch/arm/mach-mxs/soc-imx23.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <mach/imx23-regs.h>
#include <io.h>
@@ -23,18 +24,16 @@
# define HW_CLKCTRL_RESET_CHIP (1 << 1)
/* Reset the full i.MX23 SoC via a chipset feature */
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn imx23_restart_soc(struct device_d *dev)
{
u32 reg;
reg = readl(IMX_CCM_BASE + HW_CLKCTRL_RESET);
writel(reg | HW_CLKCTRL_RESET_CHIP, IMX_CCM_BASE + HW_CLKCTRL_RESET);
- while (1)
- ;
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
static int imx23_devices_init(void)
{
@@ -46,6 +45,7 @@ static int imx23_devices_init(void)
add_generic_device("imx23-gpio", 0, NULL, IMX_IOMUXC_BASE, 0x2000, IORESOURCE_MEM, NULL);
add_generic_device("imx23-gpio", 1, NULL, IMX_IOMUXC_BASE, 0x2000, IORESOURCE_MEM, NULL);
add_generic_device("imx23-gpio", 2, NULL, IMX_IOMUXC_BASE, 0x2000, IORESOURCE_MEM, NULL);
+ restart_register_handler(imx23_restart_soc, NULL, FEATURE_SCOPE_SOC);
return 0;
}
diff --git a/arch/arm/mach-mxs/soc-imx28.c b/arch/arm/mach-mxs/soc-imx28.c
index b4ec38d..ed9ae05 100644
--- a/arch/arm/mach-mxs/soc-imx28.c
+++ b/arch/arm/mach-mxs/soc-imx28.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <mach/imx28-regs.h>
#include <io.h>
@@ -24,18 +25,22 @@
#define HW_CLKCTRL_WDOG_POR_DISABLE (1 << 5)
/* Reset the full i.MX28 SoC via a chipset feature */
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn imx28_restart_soc(struct device_d *dev)
{
u32 reg;
reg = readl(IMX_CCM_BASE + HW_CLKCTRL_RESET);
writel(reg | HW_CLKCTRL_RESET_CHIP, IMX_CCM_BASE + HW_CLKCTRL_RESET);
- while (1)
- ;
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(imx28_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
static int imx28_init(void)
{
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
index 6127dde..7ae1b4c 100644
--- a/arch/arm/mach-netx/generic.c
+++ b/arch/arm/mach-netx/generic.c
@@ -15,8 +15,10 @@
*/
#include <common.h>
+#include <init.h>
#include <command.h>
#include <io.h>
+#include <restart.h>
#include <mach/netx-regs.h>
#include "eth_firmware.h"
@@ -134,14 +136,19 @@ failure:
return COMMAND_ERROR_USAGE;
}
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn netx_restart_soc(struct device_d *dev)
{
SYSTEM_REG(SYSTEM_RES_CR) = 0x01000008;
/* Not reached */
- while (1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_register_handler(netx_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
BAREBOX_CMD_START(loadxc)
.cmd = do_loadxc,
diff --git a/arch/arm/mach-nomadik/reset.c b/arch/arm/mach-nomadik/reset.c
index bb5696a..fa9f650 100644
--- a/arch/arm/mach-nomadik/reset.c
+++ b/arch/arm/mach-nomadik/reset.c
@@ -15,10 +15,12 @@
*/
#include <common.h>
+#include <init.h>
#include <io.h>
+#include <restart.h>
#include <mach/hardware.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn nomadik_restart_soc(struct device_d *dev)
{
void __iomem *src_rstsr = (void *)(NOMADIK_SRC_BASE + 0x18);
@@ -28,6 +30,11 @@ void __noreturn reset_cpu(unsigned long addr)
writel(1, src_rstsr);
/* Not reached */
- while (1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(nomadik_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-omap/am33xx_generic.c b/arch/arm/mach-omap/am33xx_generic.c
index 8ac1290..2bdb569 100644
--- a/arch/arm/mach-omap/am33xx_generic.c
+++ b/arch/arm/mach-omap/am33xx_generic.c
@@ -28,11 +28,11 @@
#include <mach/gpmc.h>
#include <restart.h>
-void __noreturn am33xx_reset_cpu(unsigned long addr)
+void __noreturn am33xx_restart_soc(struct device_d *dev)
{
writel(AM33XX_PRM_RSTCTRL_RESET, AM33XX_PRM_RSTCTRL);
- while (1);
+ hang();
}
/**
diff --git a/arch/arm/mach-omap/include/mach/am33xx-generic.h b/arch/arm/mach-omap/include/mach/am33xx-generic.h
index 03418b0..22e2647 100644
--- a/arch/arm/mach-omap/include/mach/am33xx-generic.h
+++ b/arch/arm/mach-omap/include/mach/am33xx-generic.h
@@ -28,7 +28,7 @@ u32 am33xx_running_in_flash(void);
u32 am33xx_running_in_sram(void);
u32 am33xx_running_in_sdram(void);
-void __noreturn am33xx_reset_cpu(unsigned long addr);
+void __noreturn am33xx_restart_soc(struct device_d *dev);
void am33xx_enable_per_clocks(void);
int am33xx_init(void);
diff --git a/arch/arm/mach-omap/include/mach/omap3-generic.h b/arch/arm/mach-omap/include/mach/omap3-generic.h
index 7db0838..945fe25 100644
--- a/arch/arm/mach-omap/include/mach/omap3-generic.h
+++ b/arch/arm/mach-omap/include/mach/omap3-generic.h
@@ -24,7 +24,7 @@ u32 omap3_running_in_flash(void);
u32 omap3_running_in_sram(void);
u32 omap3_running_in_sdram(void);
-void __noreturn omap3_reset_cpu(unsigned long addr);
+void __noreturn omap3_restart_soc(struct device_d *dev);
int omap3_init(void);
int omap3_devices_init(void);
diff --git a/arch/arm/mach-omap/include/mach/omap4-generic.h b/arch/arm/mach-omap/include/mach/omap4-generic.h
index e246e36..dff3330 100644
--- a/arch/arm/mach-omap/include/mach/omap4-generic.h
+++ b/arch/arm/mach-omap/include/mach/omap4-generic.h
@@ -18,7 +18,7 @@ static inline void omap4_save_bootinfo(uint32_t *info)
memcpy((void *)OMAP44XX_SRAM_SCRATCH_SPACE, info, 3 * sizeof(uint32_t));
}
-void __noreturn omap4_reset_cpu(unsigned long addr);
+void __noreturn omap4_restart_soc(struct device_d *dev);
int omap4_init(void);
int omap4_devices_init(void);
diff --git a/arch/arm/mach-omap/omap3_generic.c b/arch/arm/mach-omap/omap3_generic.c
index dbb0b5f..88455ce 100644
--- a/arch/arm/mach-omap/omap3_generic.c
+++ b/arch/arm/mach-omap/omap3_generic.c
@@ -52,13 +52,12 @@
*
* @return void
*/
-void __noreturn omap3_reset_cpu(unsigned long addr)
+void __noreturn omap3_restart_soc(struct device_d *dev)
{
writel(OMAP3_PRM_RSTCTRL_RESET, OMAP3_PRM_REG(RSTCTRL));
- while (1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
/**
* @brief Low level CPU type
diff --git a/arch/arm/mach-omap/omap4_generic.c b/arch/arm/mach-omap/omap4_generic.c
index 0b683da..2388d89 100644
--- a/arch/arm/mach-omap/omap4_generic.c
+++ b/arch/arm/mach-omap/omap4_generic.c
@@ -34,11 +34,11 @@
#define EMIF_L3_CONFIG_VAL_SYS_10_LL_0 0x0A0000FF
#define EMIF_L3_CONFIG_VAL_SYS_10_MPU_3_LL_0 0x0A300000
-void __noreturn omap4_reset_cpu(unsigned long addr)
+void __noreturn omap4_restart_soc(struct device_d *dev)
{
writel(OMAP44XX_PRM_RSTCTRL_RESET, OMAP44XX_PRM_RSTCTRL);
- while (1);
+ hang;
}
void omap4_set_warmboot_order(u32 *device_list)
diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c
index 334cf8d..35f576f 100644
--- a/arch/arm/mach-omap/omap_generic.c
+++ b/arch/arm/mach-omap/omap_generic.c
@@ -18,6 +18,7 @@
#include <boot.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <fs.h>
#include <malloc.h>
#include <libfile.h>
@@ -150,16 +151,17 @@ static int omap_env_init(void)
late_initcall(omap_env_init);
#endif
-void __noreturn reset_cpu(unsigned long addr)
+static int restart_register_feature(void)
{
if (cpu_is_omap3())
- omap3_reset_cpu(addr);
+ restart_register_handler(omap3_restart_soc, NULL, FEATURE_SCOPE_SOC);
if (cpu_is_omap4())
- omap4_reset_cpu(addr);
+ restart_register_handler(omap4_restart_soc, NULL, FEATURE_SCOPE_SOC);
if (cpu_is_am33xx())
- am33xx_reset_cpu(addr);
- while (1);
+ restart_register_handler(am33xx_restart_soc, NULL, FEATURE_SCOPE_SOC);
+ return 0;
}
+coredevice_initcall(restart_register_feature);
static int omap_soc_from_dt(void)
{
diff --git a/arch/arm/mach-pxa/common.c b/arch/arm/mach-pxa/common.c
index 2c27d81..3d6446d 100644
--- a/arch/arm/mach-pxa/common.c
+++ b/arch/arm/mach-pxa/common.c
@@ -16,6 +16,8 @@
*/
#include <common.h>
+#include <init.h>
+#include <restart.h>
#include <mach/pxa-regs.h>
#include <asm/io.h>
@@ -29,7 +31,7 @@
extern void pxa_clear_reset_source(void);
-void reset_cpu(ulong addr)
+static void __noreturn pxa_restart_soc(struct device_d *dev)
{
/* Clear last reset source */
pxa_clear_reset_source();
@@ -39,5 +41,11 @@ void reset_cpu(ulong addr)
writel(OSSR_M3, OSSR);
writel(readl(OSCR) + 368640, OSMR3); /* ... in 100 ms */
- while (1);
+ hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(pxa_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-rockchip/core.c b/arch/arm/mach-rockchip/core.c
index bab06df..f59d3d2 100644
--- a/arch/arm/mach-rockchip/core.c
+++ b/arch/arm/mach-rockchip/core.c
@@ -13,16 +13,22 @@
#include <asm/io.h>
#include <common.h>
+#include <init.h>
+#include <restart.h>
#include <mach/rockchip-regs.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn rockchip_restart_soc(struct device_d *dev)
{
/* Map bootrom from address 0 */
writel(RK_SOC_CON0_REMAP << 16, RK_GRF_BASE + RK_GRF_SOC_CON0);
/* Reset */
writel(0xeca8, RK_CRU_BASE + RK_CRU_GLB_SRST_SND);
- while (1)
- ;
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(rockchip_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-samsung/generic.c b/arch/arm/mach-samsung/generic.c
index 75965d7..7f7bc36 100644
--- a/arch/arm/mach-samsung/generic.c
+++ b/arch/arm/mach-samsung/generic.c
@@ -21,6 +21,7 @@
#include <config.h>
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <io.h>
#include <mach/s3c-iomap.h>
#include <mach/s3c-generic.h>
@@ -29,7 +30,7 @@
#define S3C_WTDAT (S3C_WATCHDOG_BASE + 0x04)
#define S3C_WTCNT (S3C_WATCHDOG_BASE + 0x08)
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn samsung_restart_soc(struct device_d *dev)
{
/* Disable watchdog */
writew(0x0000, S3C_WTCON);
@@ -41,7 +42,11 @@ void __noreturn reset_cpu(unsigned long addr)
writew(0x0021, S3C_WTCON);
/* loop forever and wait for reset to happen */
- while(1)
- ;
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(samsung_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-socfpga/reset-manager.c b/arch/arm/mach-socfpga/reset-manager.c
index a9e7e14..eca1ee3 100644
--- a/arch/arm/mach-socfpga/reset-manager.c
+++ b/arch/arm/mach-socfpga/reset-manager.c
@@ -17,6 +17,8 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <mach/socfpga-regs.h>
#include <mach/reset-manager.h>
@@ -38,7 +40,7 @@ void watchdog_disable(void)
}
/* Write the reset manager register to cause reset */
-void reset_cpu(ulong addr)
+static void __noreturn socfpga_restart_soc(struct device_d *dev)
{
/* request a warm reset */
writel((1 << RSTMGR_CTRL_SWWARMRSTREQ_LSB),
@@ -47,5 +49,11 @@ void reset_cpu(ulong addr)
* infinite loop here as watchdog will trigger and reset
* the processor
*/
- while (1);
+ hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(socfpga_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-tegra/tegra20-pmc.c b/arch/arm/mach-tegra/tegra20-pmc.c
index 6493eea..7dc54ce 100644
--- a/arch/arm/mach-tegra/tegra20-pmc.c
+++ b/arch/arm/mach-tegra/tegra20-pmc.c
@@ -36,13 +36,12 @@ static void __iomem *pmc_base;
static int tegra_num_powerdomains;
/* main SoC reset trigger */
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn tegra20_restart_soc(struct device_d *dev)
{
writel(PMC_CNTRL_MAIN_RST, pmc_base + PMC_CNTRL);
- unreachable();
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
static int tegra_powergate_set(int id, bool new_state)
{
@@ -219,7 +218,7 @@ static int tegra20_pmc_probe(struct device_d *dev)
static int do_tegrarcm(int argc, char *argv[])
{
writel(2, pmc_base + PMC_SCRATCH(0));
- reset_cpu(0);
+ restart_machine();
return 0;
}
@@ -244,6 +243,7 @@ static struct driver_d tegra20_pmc_driver = {
static int tegra20_pmc_init(void)
{
+ restart_register_handler(tegra20_restart_soc, NULL, FEATURE_SCOPE_SOC);
return platform_driver_register(&tegra20_pmc_driver);
}
coredevice_initcall(tegra20_pmc_init);
diff --git a/arch/arm/mach-uemd/reset.c b/arch/arm/mach-uemd/reset.c
deleted file mode 100644
index 00ae0be..0000000
--- a/arch/arm/mach-uemd/reset.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * This file is part of barebox.
- * 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.
- *
- */
-
-#include <common.h>
-
-void __noreturn reset_cpu(ulong addr)
-{
- hang();
-}
-EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index c671aa6..e2ceec6 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -26,6 +26,7 @@
#include <init.h>
#include <clock.h>
#include <debug_ll.h>
+#include <restart.h>
#include <linux/sizes.h>
#include <linux/clkdev.h>
@@ -184,7 +185,7 @@ void versatile_register_uart(unsigned id)
amba_apb_device_add(NULL, "uart-pl011", id, start, 4096, NULL, 0);
}
-void __noreturn reset_cpu (unsigned long ignored)
+static void versatile_reset_soc(struct device_d *dev)
{
u32 val;
@@ -195,9 +196,8 @@ void __noreturn reset_cpu (unsigned long ignored)
__raw_writel(val, VERSATILE_SYS_RESETCTL);
__raw_writel(0, VERSATILE_SYS_LOCK);
- while(1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
static int versatile_init(void)
{
@@ -205,6 +205,7 @@ static int versatile_init(void)
amba_apb_device_add(NULL, "pl061_gpio", 1, 0x101e5000, 4096, NULL, 0);
amba_apb_device_add(NULL, "pl061_gpio", 2, 0x101e6000, 4096, NULL, 0);
amba_apb_device_add(NULL, "pl061_gpio", 3, 0x101e7000, 4096, NULL, 0);
+ restart_register_handler(versatile_reset_soc, NULL, FEATURE_SCOPE_SOC);
return 0;
}
coredevice_initcall(versatile_init);
diff --git a/arch/arm/mach-vexpress/reset.c b/arch/arm/mach-vexpress/reset.c
index ad6e06f..1cbc2b3 100644
--- a/arch/arm/mach-vexpress/reset.c
+++ b/arch/arm/mach-vexpress/reset.c
@@ -6,17 +6,24 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <linux/amba/sp805.h>
#include <mach/devices.h>
void __iomem *v2m_wdt_base;
-void reset_cpu(ulong addr)
+static void vexpress_reset_soc(struct device_d *dev)
{
writel(LOAD_MIN, v2m_wdt_base + WDTLOAD);
writeb(RESET_ENABLE, v2m_wdt_base + WDTCONTROL);
- while (1)
- ;
+ hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(vexpress_reset_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-zynq/zynq.c b/arch/arm/mach-zynq/zynq.c
index bd29e13..b541da1 100644
--- a/arch/arm/mach-zynq/zynq.c
+++ b/arch/arm/mach-zynq/zynq.c
@@ -17,6 +17,7 @@
#include <asm-generic/io.h>
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <mach/zynq7000-regs.h>
static int zynq_init(void)
@@ -44,13 +45,18 @@ static int zynq_init(void)
}
postcore_initcall(zynq_init);
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn zynq_restart_soc(struct device_d *dev)
{
/* write unlock key to slcr */
writel(0xDF0D, ZYNQ_SLCR_UNLOCK);
/* reset */
writel(0x1, ZYNQ_PSS_RST_CTRL);
- while (1)
- ;
+ hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(zynq_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/blackfin/lib/cpu.c b/arch/blackfin/lib/cpu.c
index 9d4c6e3..6c72e03 100644
--- a/arch/blackfin/lib/cpu.c
+++ b/arch/blackfin/lib/cpu.c
@@ -27,8 +27,9 @@
#include <asm/entry.h>
#include <asm/cpu.h>
#include <init.h>
+#include <restart.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn blackfin_restart_cpu(struct device_d *dev)
{
icache_disable();
@@ -41,9 +42,15 @@ void __noreturn reset_cpu(unsigned long addr)
);
/* Not reached */
- while (1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_register_handler(blackfin_restart_cpu, NULL, FEATURE_SCOPE_CPU);
+}
+coredevice_initcall(restart_register_feature);
+
void icache_disable(void)
{
#ifdef __ADSPBF537__
diff --git a/arch/blackfin/lib/traps.c b/arch/blackfin/lib/traps.c
index c2dda73..08af2f4 100644
--- a/arch/blackfin/lib/traps.c
+++ b/arch/blackfin/lib/traps.c
@@ -91,7 +91,7 @@ void trap_c (struct pt_regs *regs)
printf("\nPlease reset the board\n");
- reset_cpu(0);
+ restart_machine();
}
void blackfin_irq_panic(int reason, struct pt_regs *regs)
@@ -101,6 +101,6 @@ void blackfin_irq_panic(int reason, struct pt_regs *regs)
printf("Unhandled IRQ or exceptions!\n");
printf("Please reset the board \n");
- reset_cpu(0);
+ restart_machine();
}
diff --git a/arch/efi/efi/efi.c b/arch/efi/efi/efi.c
index d351775..9d8110b 100644
--- a/arch/efi/efi/efi.c
+++ b/arch/efi/efi/efi.c
@@ -24,6 +24,7 @@
#include <command.h>
#include <magicvar.h>
#include <init.h>
+#include <restart.h>
#include <driver.h>
#include <ns16550.h>
#include <io.h>
@@ -246,13 +247,19 @@ static int efi_console_init(void)
}
console_initcall(efi_console_init);
-void reset_cpu(unsigned long addr)
+static void __noreturn efi_restart_system(struct device_d *dev)
{
RT->reset_system(EFI_RESET_WARM, EFI_SUCCESS, 0, NULL);
- while(1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_register_handler(efi_restart_cpu, NULL, FEATURE_SCOPE_MACHINE);
+}
+coredevice_initcall(restart_register_feature);
+
extern char image_base[];
extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
__barebox_initcalls_end[];
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 0e03aa9..5f4a540 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -20,7 +20,7 @@ static int do_bootm_barebox(struct image_data *data)
barebox();
- reset_cpu(0);
+ restart_machine();
}
static struct image_handler barebox_handler = {
diff --git a/arch/mips/mach-ar231x/ar231x_reset.c b/arch/mips/mach-ar231x/ar231x_reset.c
index 0788add..3724bbe 100644
--- a/arch/mips/mach-ar231x/ar231x_reset.c
+++ b/arch/mips/mach-ar231x/ar231x_reset.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <linux/err.h>
#include <mach/ar2312_regs.h>
@@ -17,16 +18,16 @@
static void __iomem *reset_base;
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn ar2312x_restart_soc(struct device_d *dev)
{
printf("reseting cpu\n");
__raw_writel(0x10000,
(char *)KSEG1ADDR(AR2312_WD_TIMER));
__raw_writel(AR2312_WD_CTRL_RESET,
(char *)KSEG1ADDR(AR2312_WD_CTRL));
- unreachable();
+
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
static u32 ar231x_reset_readl(void)
{
@@ -69,6 +70,7 @@ static struct driver_d ar231x_reset_driver = {
static int ar231x_reset_init(void)
{
+ restart_register_handler(ar2312x_restart_soc, NULL, FEATURE_SCOPE_SOC);
return platform_driver_register(&ar231x_reset_driver);
}
coredevice_initcall(ar231x_reset_init);
diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
index a0e9b34..757027f 100644
--- a/arch/mips/mach-ath79/reset.c
+++ b/arch/mips/mach-ath79/reset.c
@@ -16,9 +16,11 @@
*/
#include <common.h>
+#include <init.h>
+#include <restart.h>
#include <mach/ath79.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn ath79_restart_soc(struct device_d *dev)
{
ath79_reset_wr(AR933X_RESET_REG_RESET_MODULE, AR71XX_RESET_FULL_CHIP);
/*
@@ -26,7 +28,12 @@ void __noreturn reset_cpu(ulong addr)
* pulling the reset pin. The system will reboot with PLL disabled.
* Always zero when read.
*/
- unreachable();
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(ath79_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/mips/mach-bcm47xx/reset.c b/arch/mips/mach-bcm47xx/reset.c
index 00aee19..332047d 100644
--- a/arch/mips/mach-bcm47xx/reset.c
+++ b/arch/mips/mach-bcm47xx/reset.c
@@ -17,12 +17,20 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <mach/hardware.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn bcm47xx_restart_soc(struct device_d *dev)
{
__raw_writel(GORESET, (char *)SOFTRES_REG);
- while (1);
+
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(bcm47xx_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/mips/mach-loongson/loongson1_reset.c b/arch/mips/mach-loongson/loongson1_reset.c
index 8975392..fe02da6 100644
--- a/arch/mips/mach-loongson/loongson1_reset.c
+++ b/arch/mips/mach-loongson/loongson1_reset.c
@@ -14,14 +14,21 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <mach/loongson1.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn longhorn_restart_soc(struct device_d *dev)
{
__raw_writel(0x1, LS1X_WDT_EN);
__raw_writel(0x1, LS1X_WDT_SET);
__raw_writel(0x1, LS1X_WDT_TIMER);
- unreachable();
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(longhorn_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/mips/mach-malta/reset.c b/arch/mips/mach-malta/reset.c
index f1dc68a..066535c 100644
--- a/arch/mips/mach-malta/reset.c
+++ b/arch/mips/mach-malta/reset.c
@@ -22,12 +22,20 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <mach/hardware.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn malta_restart_soc(struct device_d *dev)
{
__raw_writel(GORESET, (char *)SOFTRES_REG);
- while (1);
+
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(malta_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/nios2/cpu/cpu.c b/arch/nios2/cpu/cpu.c
index fdbe9f9..3ede3b8 100644
--- a/arch/nios2/cpu/cpu.c
+++ b/arch/nios2/cpu/cpu.c
@@ -18,14 +18,22 @@
*/
#include <common.h>
+#include <init.h>
+#include <restart.h>
#include <asm/system.h>
-void __noreturn reset_cpu(ulong ignored)
+static void __noreturn nios2_restart_soc(struct device_d *dev)
{
/* indirect call to go beyond 256MB limitation of toolchain */
nios2_callr(RESET_ADDR);
/* Not reached */
- while (1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_register_handler(nios2_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
+
diff --git a/arch/openrisc/cpu/cpu.c b/arch/openrisc/cpu/cpu.c
index d73a418..6cedb26 100644
--- a/arch/openrisc/cpu/cpu.c
+++ b/arch/openrisc/cpu/cpu.c
@@ -19,6 +19,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <asm/system.h>
#include <asm/openrisc_exc.h>
@@ -29,11 +30,17 @@ int cleanup_before_linux(void)
extern void __reset(void);
-void __noreturn reset_cpu(ulong ignored)
+static void __noreturn openrisc_restart_cpu(struct device_d *dev)
{
__reset();
/* not reached, __reset does not return */
/* Not reached */
- while (1);
+ hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_register_handler(openrisc_restart_cpu, NULL, FEATURE_SCOPE_CPU);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/ppc/lib/ppclinux.c b/arch/ppc/lib/ppclinux.c
index e25efec..e13ba5b 100644
--- a/arch/ppc/lib/ppclinux.c
+++ b/arch/ppc/lib/ppclinux.c
@@ -87,7 +87,7 @@ static int do_bootm_linux(struct image_data *data)
*/
kernel(data->oftree, kernel, 0, 0, 0);
- reset_cpu(0);
+ restart_machine();
error:
return -1;
diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c
index c860e70..c11a6cd 100644
--- a/arch/ppc/mach-mpc5xxx/cpu.c
+++ b/arch/ppc/mach-mpc5xxx/cpu.c
@@ -31,6 +31,7 @@
#include <types.h>
#include <errno.h>
#include <of.h>
+#include <restart.h>
#include <mach/clocks.h>
int checkcpu (void)
@@ -59,7 +60,7 @@ int checkcpu (void)
/* ------------------------------------------------------------------------- */
-void __noreturn reset_cpu (unsigned long addr)
+static void __noreturn mpc5xxx_restart_soc(struct device_d *dev)
{
ulong msr;
/* Interrupts and MMU off */
@@ -71,9 +72,15 @@ void __noreturn reset_cpu (unsigned long addr)
/* Charge the watchdog timer */
*(vu_long *)(MPC5XXX_GPT0_COUNTER) = 0x0001000f;
*(vu_long *)(MPC5XXX_GPT0_ENABLE) = 0x9004; /* wden|ce|timer_ms */
- while(1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_register_handler(mpc5xxx_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
+
/* ------------------------------------------------------------------------- */
#ifdef CONFIG_OFTREE
diff --git a/arch/ppc/mach-mpc85xx/cpu.c b/arch/ppc/mach-mpc85xx/cpu.c
index 7c183c1..a3fedae 100644
--- a/arch/ppc/mach-mpc85xx/cpu.c
+++ b/arch/ppc/mach-mpc85xx/cpu.c
@@ -26,12 +26,13 @@
#include <common.h>
#include <memory.h>
#include <init.h>
+#include <restart.h>
#include <asm/fsl_ddr_sdram.h>
#include <asm-generic/memory_layout.h>
#include <mach/mmu.h>
#include <mach/immap_85xx.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn mpc85xx_restart_soc(struct device_d *dev)
{
void __iomem *regs = (void __iomem *)MPC85xx_GUTS_ADDR;
@@ -39,10 +40,15 @@ void __noreturn reset_cpu(unsigned long addr)
out_be32(regs + MPC85xx_GUTS_RSTCR_OFFSET, 0x2); /* HRESET_REQ */
udelay(100);
- while (1)
- ;
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_register_handler(mpc85xx_restart_soc, NULL, FEATURE_SCOPE_SOC);
+}
+coredevice_initcall(restart_register_feature);
+
long int initdram(int board_type)
{
phys_size_t dram_size = 0;
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c
index d627391..6a2e261 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -28,6 +28,8 @@
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
+#include <init.h>
+#include <restart.h>
#include <time.h>
#include <getopt.h>
#include <sys/types.h>
@@ -115,12 +117,18 @@ uint64_t linux_get_time(void)
return now;
}
-void __attribute__((noreturn)) reset_cpu(unsigned long addr)
+static void __attribute__((noreturn)) sandbox_restart_cpu(struct device_d *dev)
{
cookmode();
exit(0);
}
+static int restart_register_feature(void)
+{
+ restart_register_handler(sandbox_restart_cpu, NULL, FEATURE_SCOPE_CPU);
+}
+coredevice_initcall(restart_register_feature);
+
int linux_read(int fd, void *buf, size_t count)
{
ssize_t ret;
@@ -133,7 +141,7 @@ int linux_read(int fd, void *buf, size_t count)
if (ret == 0) {
printf("read on fd %d returned 0, device gone? - exiting\n", fd);
- reset_cpu(0);
+ restart_machine();
} else if (ret == -1) {
if (errno == EAGAIN)
return -errno;
@@ -141,7 +149,7 @@ int linux_read(int fd, void *buf, size_t count)
continue;
else {
printf("read on fd %d returned -1, errno %d - exiting\n", fd, errno);
- reset_cpu(0);
+ restart_machine();
}
}
} while (ret <= 0);
diff --git a/arch/x86/mach-i386/reset.c b/arch/x86/mach-i386/reset.c
deleted file mode 100644
index 65f7d35..0000000
--- a/arch/x86/mach-i386/reset.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2009 Juergen Beisert, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * 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.
- *
- *
- */
-
-/**
- * @file
- * @brief Resetting an x86 CPU
- */
-
-#include <common.h>
-
-void __noreturn reset_cpu(unsigned long addr)
-{
- /** How to reset the machine? */
- while(1)
- ;
-}
-EXPORT_SYMBOL(reset_cpu);
diff --git a/commands/reset.c b/commands/reset.c
index 4f42b91..8300480 100644
--- a/commands/reset.c
+++ b/commands/reset.c
@@ -21,6 +21,7 @@
#include <command.h>
#include <complete.h>
#include <getopt.h>
+#include <restart.h>
static int cmd_reset(int argc, char *argv[])
{
@@ -39,7 +40,7 @@ static int cmd_reset(int argc, char *argv[])
if (shutdown_flag)
shutdown_barebox();
- reset_cpu(0);
+ restart_machine();
/* Not reached */
return 1;
diff --git a/common/misc.c b/common/misc.c
index 6da71c7..5532349 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/restart.c b/common/restart.c
index 5b53264..cfdc463 100644
--- a/common/restart.c
+++ b/common/restart.c
@@ -56,12 +56,65 @@ void reset_source_set(enum reset_src_type st, enum f_scope scope)
}
EXPORT_SYMBOL(reset_source_set);
+/* handle machine restart feature */
+
+static struct device_d *resetd;
+static void (*resetf)(struct device_d*);
+static int restart_scope;
+
+void __noreturn restart_machine(void)
+{
+ if (resetf != NULL)
+ resetf(resetd);
+ else
+ pr_err("No restart handler registered.\n");
+
+ hang();
+}
+
+static void restart_update_global_info(void)
+{
+ globalvar_add_simple("system.restart.unit",
+ resetd == NULL ? "unknown" : resetd->name);
+}
+
+int restart_register_handler(void (*func)(struct device_d*), struct device_d *dev, enum f_scope scope)
+{
+ /* calling with a lower or equal scope will be ignored and is not a failure */
+ if (scope <= restart_scope)
+ return 0;
+
+ resetf = func;
+ resetd = dev;
+ restart_scope = scope;
+ restart_update_global_info();
+
+ return 0;
+}
+EXPORT_SYMBOL(restart_register_handler);
+
+void restart_remove_handler(void (*func)(struct device_d*), struct device_d *dev)
+{
+ /* we just ignore a not matching call */
+ if (func != resetf || resetd != dev)
+ return;
+
+ resetf = NULL;
+ resetd = NULL;
+ restart_scope = FEATURE_SCOPE_UNKNOWN;
+ restart_update_global_info();
+}
+EXPORT_SYMBOL(restart_remove_handler);
+
static int reset_feature_init(void)
{
globalvar_add_simple_enum("system.reset", &reset_source, reset_src_names,
ARRAY_SIZE(reset_src_names));
globalvar_add_simple_enum("system.reset.scope", &reset_source_scope,
scope_names, ARRAY_SIZE(scope_names));
+ globalvar_add_simple_enum("system.restart.scope", &restart_scope,
+ scope_names, ARRAY_SIZE(scope_names));
+ restart_update_global_info();
return 0;
}
coredevice_initcall(reset_feature_init);
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 76879db..bf28f7c 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -31,6 +31,7 @@
#include <progress.h>
#include <environment.h>
#include <globalvar.h>
+#include <restart.h>
#include <usb/ch9.h>
#include <usb/gadget.h>
#include <usb/fastboot.h>
@@ -520,7 +521,7 @@ static int fastboot_tx_print(struct f_fastboot *f_fb, const char *fmt, ...)
static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
{
- reset_cpu(0);
+ restart_machine();
}
static void cb_reboot(struct usb_ep *ep, struct usb_request *req, const char *cmd)
diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
index f3decae..3cbae09 100644
--- a/drivers/watchdog/imxwd.c
+++ b/drivers/watchdog/imxwd.c
@@ -121,12 +121,11 @@ static int imx_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
return priv->ops->set_timeout(priv, timeout);
}
-static struct imx_wd *reset_wd;
-
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn imxwd_force_soc_reset(struct device_d *dev)
{
- if (reset_wd)
- reset_wd->ops->set_timeout(reset_wd, -1);
+ struct imx_wd *reset_wd = dev->priv;
+
+ reset_wd->ops->set_timeout(reset_wd, -1);
mdelay(1000);
@@ -158,6 +157,7 @@ static void imx_watchdog_detect_reset_source(struct imx_wd *priv)
static int imx21_wd_init(struct imx_wd *priv)
{
imx_watchdog_detect_reset_source(priv);
+ restart_register_handler(imxwd_force_soc_reset, priv->dev, FEATURE_SCOPE_SOC);
/*
* Disable watchdog powerdown counter
@@ -187,9 +187,6 @@ static int imx_wd_probe(struct device_d *dev)
priv->wd.set_timeout = imx_watchdog_set_timeout;
priv->dev = dev;
- if (!reset_wd)
- reset_wd = priv;
-
if (IS_ENABLED(CONFIG_WATCHDOG_IMX)) {
ret = watchdog_register(&priv->wd);
if (ret)
@@ -212,8 +209,7 @@ error_unregister:
if (IS_ENABLED(CONFIG_WATCHDOG_IMX))
watchdog_deregister(&priv->wd);
on_error:
- if (reset_wd && reset_wd != priv)
- free(priv);
+ free(priv);
return ret;
}
@@ -221,11 +217,12 @@ static void imx_wd_remove(struct device_d *dev)
{
struct imx_wd *priv = dev->priv;
+ restart_remove_handler(imxwd_force_soc_reset, dev);
+
if (IS_ENABLED(CONFIG_WATCHDOG_IMX))
watchdog_deregister(&priv->wd);
- if (reset_wd && reset_wd != priv)
- free(priv);
+ free(priv);
}
static const struct imx_wd_ops imx21_wd_ops = {
diff --git a/drivers/watchdog/jz4740.c b/drivers/watchdog/jz4740.c
index 8ac51e0..dcaa62f 100644
--- a/drivers/watchdog/jz4740.c
+++ b/drivers/watchdog/jz4740.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <io.h>
#define JZ_REG_WDT_TIMER_DATA 0x0
@@ -42,30 +43,26 @@ struct jz4740_wdt_drvdata {
void __iomem *base;
};
-static struct jz4740_wdt_drvdata *reset_wd;
-
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn jz4740_reset_soc(struct device_d *dev)
{
- if (reset_wd) {
- void __iomem *base = reset_wd->base;
+ struct jz4740_wdt_drvdata *reset_wd = dev->priv;
+
+ void __iomem *base = reset_wd->base;
- writew(JZ_WDT_CLOCK_DIV_4 | JZ_WDT_CLOCK_EXT,
- base + JZ_REG_WDT_TIMER_CONTROL);
- writew(0, base + JZ_REG_WDT_TIMER_COUNTER);
+ writew(JZ_WDT_CLOCK_DIV_4 | JZ_WDT_CLOCK_EXT,
+ base + JZ_REG_WDT_TIMER_CONTROL);
+ writew(0, base + JZ_REG_WDT_TIMER_COUNTER);
- /* reset after 4ms */
- writew(JZ_EXTAL / 1000, base + JZ_REG_WDT_TIMER_DATA);
+ /* reset after 4ms */
+ writew(JZ_EXTAL / 1000, base + JZ_REG_WDT_TIMER_DATA);
- /* start wdt */
- writeb(0x1, base + JZ_REG_WDT_COUNTER_ENABLE);
+ /* start wdt */
+ writeb(0x1, base + JZ_REG_WDT_COUNTER_ENABLE);
- mdelay(1000);
- } else
- pr_err("%s: can't reset cpu\n", __func__);
+ mdelay(1000);
hang();
}
-EXPORT_SYMBOL(reset_cpu);
static int jz4740_wdt_probe(struct device_d *dev)
{
@@ -78,11 +75,9 @@ static int jz4740_wdt_probe(struct device_d *dev)
return -ENODEV;
}
- if (!reset_wd)
- reset_wd = priv;
-
dev->priv = priv;
+ restart_register_handler(jz4740_reset_soc, dev, FEATURE_SCOPE_SOC);
return 0;
}
diff --git a/include/common.h b/include/common.h
index eef371c..e658593 100644
--- a/include/common.h
+++ b/include/common.h
@@ -67,7 +67,6 @@ int readline (const char *prompt, char *buf, int len);
long get_ram_size (volatile long *, long);
/* $(CPU)/cpu.c */
-void __noreturn reset_cpu(unsigned long addr);
void __noreturn poweroff(void);
/* lib_$(ARCH)/time.c */
diff --git a/include/restart.h b/include/restart.h
index 4215760..e1ba082 100644
--- a/include/restart.h
+++ b/include/restart.h
@@ -37,4 +37,10 @@ enum reset_src_type {
void reset_source_set(enum reset_src_type, enum f_scope);
enum reset_src_type reset_source_get(void);
+/* restart feature */
+
+int restart_register_handler(void (*func)(struct device_d*), struct device_d *, enum f_scope);
+void restart_remove_handler(void (*func)(struct device_d*), struct device_d *);
+void __noreturn restart_machine(void);
+
#endif /* __INCLUDE_SYSTEM_RESTART_H */
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread