[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] xen/rpi4: implement watchdog-based reset



On Wed, Jun 03, 2020 at 03:31:56PM -0700, Stefano Stabellini wrote:
> Touching the watchdog is required to be able to reboot the board.
> 
> The implementation is based on
> drivers/watchdog/bcm2835_wdt.c:__bcm2835_restart in Linux.

Ah, I was looking at this just today, as it had been annoying me
greatly.  This works for me, so:

Tested-by: Corey Minyard <cminyard@xxxxxxxxxx>

However, I was wondering if it might be better to handle this by failing
the operation in xen and passing it back to dom0 to do.  On the Pi you
send a firmware message to reboot, and that seems like too much to do in
Xen, but it would seem possible to send this back to dom0.  Just a
thought, as it might be a more general fix for other devices in the same
situation.

Thanks,

-corey

> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxx>
> ---
>  xen/arch/arm/platforms/brcm-raspberry-pi.c | 60 ++++++++++++++++++++++
>  1 file changed, 60 insertions(+)
> 
> diff --git a/xen/arch/arm/platforms/brcm-raspberry-pi.c 
> b/xen/arch/arm/platforms/brcm-raspberry-pi.c
> index f5ae58a7d5..0214ae2b3c 100644
> --- a/xen/arch/arm/platforms/brcm-raspberry-pi.c
> +++ b/xen/arch/arm/platforms/brcm-raspberry-pi.c
> @@ -18,6 +18,10 @@
>   */
>  
>  #include <asm/platform.h>
> +#include <xen/delay.h>
> +#include <xen/mm.h>
> +#include <xen/vmap.h>
> +#include <asm/io.h>
>  
>  static const char *const rpi4_dt_compat[] __initconst =
>  {
> @@ -37,12 +41,68 @@ static const struct dt_device_match rpi4_blacklist_dev[] 
> __initconst =
>       * The aux peripheral also shares a page with the aux UART.
>       */
>      DT_MATCH_COMPATIBLE("brcm,bcm2835-aux"),
> +    /* Special device used for rebooting */
> +    DT_MATCH_COMPATIBLE("brcm,bcm2835-pm"),
>      { /* sentinel */ },
>  };
>  
> +
> +#define PM_PASSWORD         0x5a000000
> +#define PM_RSTC             0x1c
> +#define PM_WDOG             0x24
> +#define PM_RSTC_WRCFG_FULL_RESET    0x00000020
> +#define PM_RSTC_WRCFG_CLR           0xffffffcf
> +
> +static void __iomem *rpi4_map_watchdog(void)
> +{
> +    void __iomem *base;
> +    struct dt_device_node *node;
> +    paddr_t start, len;
> +    int ret;
> +
> +    node = dt_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm");
> +    if ( !node )
> +        return NULL;
> +
> +    ret = dt_device_get_address(node, 0, &start, &len);
> +    if ( ret )
> +    {
> +        dprintk(XENLOG_ERR, "Cannot read watchdog register address\n");
> +        return NULL;
> +    }
> +
> +    base = ioremap_nocache(start & PAGE_MASK, PAGE_SIZE);
> +    if ( !base )
> +    {
> +        dprintk(XENLOG_ERR, "Unable to map watchdog register!\n");
> +        return NULL;
> +    }
> +
> +    return base;
> +}
> +
> +static void rpi4_reset(void)
> +{
> +    u32 val;
> +    void __iomem *base = rpi4_map_watchdog();
> +    if ( !base )
> +        return;
> +
> +    /* use a timeout of 10 ticks (~150us) */
> +    writel(10 | PM_PASSWORD, base + PM_WDOG);
> +    val = readl(base + PM_RSTC);
> +    val &= PM_RSTC_WRCFG_CLR;
> +    val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
> +    writel(val, base + PM_RSTC);
> +
> +    /* No sleeping, possibly atomic. */
> +    mdelay(1);
> +}
> +
>  PLATFORM_START(rpi4, "Raspberry Pi 4")
>      .compatible     = rpi4_dt_compat,
>      .blacklist_dev  = rpi4_blacklist_dev,
> +    .reset = rpi4_reset,
>      .dma_bitsize    = 30,
>  PLATFORM_END
>  
> -- 
> 2.17.1
> 



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.