The watchdog peripheral on the Raspberry Pi can be used to shutdown by writing a magic value that the firmware checks for and rebooting. This is useful to close an emulated Raspberry Pi in QEMU, so add support. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- drivers/watchdog/bcm2835_wdt.c | 21 +++++++++++++++++++++ include/soc/bcm283x/wdt.h | 7 +++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c index 874315d502a9..5b854c49b311 100644 --- a/drivers/watchdog/bcm2835_wdt.c +++ b/drivers/watchdog/bcm2835_wdt.c @@ -8,6 +8,7 @@ #include <init.h> #include <io.h> #include <restart.h> +#include <poweroff.h> #include <watchdog.h> #include <soc/bcm283x/wdt.h> @@ -23,6 +24,7 @@ struct bcm2835_wd { void __iomem *base; struct device *dev; struct restart_handler restart; + struct poweroff_handler poweroff; }; #define RESET_TIMEOUT 10 @@ -41,6 +43,20 @@ static void __noreturn bcm2835_restart_soc(struct restart_handler *rst) hang(); } +static void __noreturn bcm2835_poweroff_soc(struct poweroff_handler *poweroff) +{ + struct bcm2835_wd *priv = container_of(poweroff, struct bcm2835_wd, poweroff); + uint32_t val; + + shutdown_barebox(); + + val = readl_relaxed(priv->base + PM_RSTS); + val |= PM_PASSWORD | PM_RSTS_RASPBERRYPI_HALT; + writel_relaxed(val, priv->base + PM_RSTS); + + bcm2835_restart_soc(&priv->restart); +} + static int bcm2835_wd_set_timeout(struct watchdog *wd, unsigned timeout) { struct bcm2835_wd *priv = container_of(wd, struct bcm2835_wd, wd); @@ -86,6 +102,11 @@ static int bcm2835_wd_probe(struct device *dev) } } + priv->poweroff.name = "bcm2835_wd"; + priv->poweroff.poweroff = bcm2835_poweroff_soc; + + poweroff_handler_register(&priv->poweroff); + priv->restart.name = "bcm2835_wd"; priv->restart.restart = bcm2835_restart_soc; diff --git a/include/soc/bcm283x/wdt.h b/include/soc/bcm283x/wdt.h index 2002647b9c39..86e02bcf40f7 100644 --- a/include/soc/bcm283x/wdt.h +++ b/include/soc/bcm283x/wdt.h @@ -38,4 +38,11 @@ #define PM_RSTS_HADSR_SET \ (PM_RSTS_HADSRQ_SET | PM_RSTS_HADSRF_SET | PM_RSTS_HADSRH_SET) +/* + * The Raspberry Pi firmware uses the RSTS register to know which partition + * to boot from. The partition value is spread into bits 0, 2, 4, 6, 8, 10. + * Partition 63 is a special partition used by the firmware to indicate halt. + */ +#define PM_RSTS_RASPBERRYPI_HALT 0x555 + #endif -- 2.39.2