Message ID | 1394978030-14511-4-git-send-email-hdegoede@redhat.com |
---|---|
State | RFC |
Delegated to: | Albert ARIBAUD |
Headers | show |
On Sun, 2014-03-16 at 14:53 +0100, Hans de Goede wrote: > There is no way to reset the cpu, so use the watchdog for this. The sunxi.git tree does this by calling watchdog_set(0). I think it would be better to introduce the generic watchdog support and the add this a patch to use it for reset. Unless we don't plan to upstream the watchdog stuff for some reason? Not sure why cmd_watchdog.c is sunxi, seems like in principal it could be generic. Ian. > Signed-off-by: Hans de Goede <hdegoede@redhat.com> > --- > arch/arm/cpu/armv7/sunxi/board.c | 7 +++++++ > arch/arm/include/asm/arch-sunxi/timer.h | 4 ++++ > 2 files changed, 11 insertions(+) > > diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c > index 98cad43..2668d52 100644 > --- a/arch/arm/cpu/armv7/sunxi/board.c > +++ b/arch/arm/cpu/armv7/sunxi/board.c > @@ -70,6 +70,13 @@ int gpio_init(void) > > void reset_cpu(ulong addr) > { > + static const struct sunxi_wdog *wdog = > + &((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog; > + > + /* Set the watchdog for its shortest interval (.5s) and wait */ > + writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); > + writel(WDT_CTRL_RESTART, &wdog->ctl); > + while (1); > } > > /* do some early init */ > diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h > index f9d4f4f..1489b2e 100644 > --- a/arch/arm/include/asm/arch-sunxi/timer.h > +++ b/arch/arm/include/asm/arch-sunxi/timer.h > @@ -27,6 +27,10 @@ > #ifndef _SUNXI_TIMER_H_ > #define _SUNXI_TIMER_H_ > > +#define WDT_CTRL_RESTART (0x1 << 0) > +#define WDT_MODE_EN (0x1 << 0) > +#define WDT_MODE_RESET_EN (0x1 << 1) > + > #ifndef __ASSEMBLY__ > > #include <linux/types.h>
sön 2014-03-16 klockan 14:53 +0100 skrev Hans de Goede: > void reset_cpu(ulong addr) > { > + static const struct sunxi_wdog *wdog = > + &((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog; > + > + /* Set the watchdog for its shortest interval (.5s) and wait */ > + writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); > + writel(WDT_CTRL_RESTART, &wdog->ctl); > + while (1); This code is incomplete and do not reload the watchdog if already running. wdog->ctl is locked by a magic key. Should use writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); where #define WDT_CTRL_KEY (0x0a57 << 1) Unfortunatley Allwinner kindly omitted this little detail from the User Manual. Found out while trying to use the watchdog as a watchdog and not only reset. Asked Tom while he still was at Allwinner and got clarification on how to use the watchdog control register. Regards Henrik
sön 2014-03-16 klockan 18:38 +0000 skrev Ian Campbell: > Not sure why cmd_watchdog.c is sunxi, seems like in principal it could > be generic. In principal it could, but there is no common API for setting the watchdog timer, and no common API for disabling the watchdog once armed. Regards Henrik
Hi, On 03/24/2014 12:53 AM, Henrik Nordström wrote: > sön 2014-03-16 klockan 14:53 +0100 skrev Hans de Goede: >> void reset_cpu(ulong addr) >> { >> + static const struct sunxi_wdog *wdog = >> + &((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog; >> + >> + /* Set the watchdog for its shortest interval (.5s) and wait */ >> + writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); >> + writel(WDT_CTRL_RESTART, &wdog->ctl); >> + while (1); > > This code is incomplete and do not reload the watchdog if already > running. wdog->ctl is locked by a magic key. Should use > > writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); > > where > > #define WDT_CTRL_KEY (0x0a57 << 1) > > Unfortunatley Allwinner kindly omitted this little detail from the User > Manual. > > Found out while trying to use the watchdog as a watchdog and not only > reset. Asked Tom while he still was at Allwinner and got clarification > on how to use the watchdog control register. Thanks, I'm currently working on v2 of this series and I've included this fix. Regards, Hans
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index 98cad43..2668d52 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -70,6 +70,13 @@ int gpio_init(void) void reset_cpu(ulong addr) { + static const struct sunxi_wdog *wdog = + &((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog; + + /* Set the watchdog for its shortest interval (.5s) and wait */ + writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); + writel(WDT_CTRL_RESTART, &wdog->ctl); + while (1); } /* do some early init */ diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h index f9d4f4f..1489b2e 100644 --- a/arch/arm/include/asm/arch-sunxi/timer.h +++ b/arch/arm/include/asm/arch-sunxi/timer.h @@ -27,6 +27,10 @@ #ifndef _SUNXI_TIMER_H_ #define _SUNXI_TIMER_H_ +#define WDT_CTRL_RESTART (0x1 << 0) +#define WDT_MODE_EN (0x1 << 0) +#define WDT_MODE_RESET_EN (0x1 << 1) + #ifndef __ASSEMBLY__ #include <linux/types.h>
There is no way to reset the cpu, so use the watchdog for this. Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- arch/arm/cpu/armv7/sunxi/board.c | 7 +++++++ arch/arm/include/asm/arch-sunxi/timer.h | 4 ++++ 2 files changed, 11 insertions(+)