diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2015-08-26 09:04:45 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2015-08-27 21:37:03 +0200 |
commit | 83b0a5ae055bc084938dac96b3ea1c796d99d86c (patch) | |
tree | ba69e2015cbfeb1626f7ea3f6bf850556541095a /drivers | |
parent | 167e93947e9b755b54900ae9870dbcc089f8d6c9 (diff) | |
download | barebox-83b0a5ae055bc084938dac96b3ea1c796d99d86c.tar.gz barebox-83b0a5ae055bc084938dac96b3ea1c796d99d86c.tar.xz |
restart: replace reset_cpu with registered restart handlers
This replaces the reset_cpu() function which every SoC or board must
provide with registered handlers. This makes it possible to have multiple
reset functions for boards which have multiple ways to reset the machine.
Also boards which have no way at all to reset the machine no longer
have to provide a dummy reset_cpu() function.
The problem this solves is that some machines have external PMICs or
similar to reset the system which have to be preferred over the
internal SoC reset, because the PMIC can reset not only the SoC but also
the external devices.
To pick the right way to reset a machine each handler has a priority. The
default priority is 100 and all currently existing restart handlers are
registered with this priority. of_get_restart_priority() allows to retrieve
the priority from the device tree which makes it possible for boards to
give certain restart handlers a higher priority in order to use this one
instead of the default one.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/f_fastboot.c | 3 | ||||
-rw-r--r-- | drivers/watchdog/imxwd.c | 22 | ||||
-rw-r--r-- | drivers/watchdog/jz4740.c | 37 |
3 files changed, 32 insertions, 30 deletions
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 76879db1f1..bf28f7c22a 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 9f09f6ecd0..4621d4125a 100644 --- a/drivers/watchdog/imxwd.c +++ b/drivers/watchdog/imxwd.c @@ -18,6 +18,7 @@ #include <of.h> #include <errno.h> #include <malloc.h> +#include <restart.h> #include <watchdog.h> #include <reset_source.h> @@ -33,6 +34,7 @@ struct imx_wd { void __iomem *base; struct device_d *dev; const struct imx_wd_ops *ops; + struct restart_handler restart; }; #define to_imx_wd(h) container_of(h, struct imx_wd, wd) @@ -121,12 +123,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 restart_handler *rst) { - if (reset_wd) - reset_wd->ops->set_timeout(reset_wd, -1); + struct imx_wd *priv = container_of(rst, struct imx_wd, restart); + + priv->ops->set_timeout(priv, -1); mdelay(1000); @@ -187,9 +188,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) @@ -206,14 +204,18 @@ static int imx_wd_probe(struct device_d *dev) dev->priv = priv; + priv->restart.name = "imxwd"; + priv->restart.restart = imxwd_force_soc_reset; + + restart_handler_register(&priv->restart); + return 0; 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; } diff --git a/drivers/watchdog/jz4740.c b/drivers/watchdog/jz4740.c index 8ac51e060a..3d45b46ee2 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 @@ -39,33 +40,30 @@ #define JZ_EXTAL 24000000 struct jz4740_wdt_drvdata { + struct restart_handler restart; void __iomem *base; }; -static struct jz4740_wdt_drvdata *reset_wd; - -void __noreturn reset_cpu(unsigned long addr) +static void __noreturn jz4740_reset_soc(struct restart_handler *rst) { - if (reset_wd) { - void __iomem *base = reset_wd->base; + struct jz4740_wdt_drvdata *priv = + container_of(rst, struct jz4740_wdt_drvdata, restart); + void __iomem *base = priv->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 +76,12 @@ static int jz4740_wdt_probe(struct device_d *dev) return -ENODEV; } - if (!reset_wd) - reset_wd = priv; - dev->priv = priv; + priv->restart.name = "jz4740-wdt"; + priv->restart.restart = jz4740_reset_soc; + restart_handler_register(&priv->restart); + return 0; } |