Message ID | 1412426248-20050-4-git-send-email-wens@csie.org |
---|---|
State | Accepted |
Delegated to: | Ian Campbell |
Headers | show |
On Sat, 2014-10-04 at 20:37 +0800, Chen-Yu Tsai wrote: > +#else /* CONFIG_SUN6I || CONFIG_SUN8I || .. */ > + 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_CFG_RESET, &wdog->cfg); > + writel(WDT_MODE_EN, &wdog->mode); > + writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); That's annoyingly close to the 4/5/7i version, but not quite close enough to allow any meaningful sharing :-/ > + while (1) { > + /* sun5i sometimes gets stuck without this */ Is this not therefore unnecessary on 6i/8i? > + writel(WDT_MODE_EN, &wdog->mode); > + } > +#endif > } > > /* do some early init */ > diff --git a/arch/arm/include/asm/arch-sunxi/watchdog.h b/arch/arm/include/asm/arch-sunxi/watchdog.h > index 5b755e3..ccc8fa3 100644 > --- a/arch/arm/include/asm/arch-sunxi/watchdog.h > +++ b/arch/arm/include/asm/arch-sunxi/watchdog.h > @@ -12,6 +12,9 @@ > > #define WDT_CTRL_RESTART (0x1 << 0) > #define WDT_CTRL_KEY (0x0a57 << 1) > + > +#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) > + > #define WDT_MODE_EN (0x1 << 0) > #define WDT_MODE_RESET_EN (0x1 << 1) > > @@ -21,4 +24,21 @@ struct sunxi_wdog { > u32 res[2]; > }; > > +#else > + > +#define WDT_CFG_RESET (0x1) > +#define WDT_MODE_EN (0x1) > + > +struct sunxi_wdog { > + u32 irq_en; /* 0x00 */ > + u32 irq_sta; /* 0x04 */ > + u32 res1[2]; > + u32 ctl; /* 0x10 */ > + u32 cfg; /* 0x14 */ > + u32 mode; /* 0x18 */ > + u32 res2; > +}; > + > +#endif > + > #endif /* _SUNXI_WATCHDOG_H_ */
On Sat, Oct 11, 2014 at 11:33 PM, Ian Campbell <ijc@hellion.org.uk> wrote: > On Sat, 2014-10-04 at 20:37 +0800, Chen-Yu Tsai wrote: >> +#else /* CONFIG_SUN6I || CONFIG_SUN8I || .. */ >> + 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_CFG_RESET, &wdog->cfg); >> + writel(WDT_MODE_EN, &wdog->mode); >> + writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); > > That's annoyingly close to the 4/5/7i version, but not quite close > enough to allow any meaningful sharing :-/ I suppose it is possible to share using clrsetbits... >> + while (1) { >> + /* sun5i sometimes gets stuck without this */ > > Is this not therefore unnecessary on 6i/8i? The kernel restart driver uses this. But Allwinner's original code does not. ChenYu >> + writel(WDT_MODE_EN, &wdog->mode); >> + } >> +#endif >> } >> >> /* do some early init */ >> diff --git a/arch/arm/include/asm/arch-sunxi/watchdog.h b/arch/arm/include/asm/arch-sunxi/watchdog.h >> index 5b755e3..ccc8fa3 100644 >> --- a/arch/arm/include/asm/arch-sunxi/watchdog.h >> +++ b/arch/arm/include/asm/arch-sunxi/watchdog.h >> @@ -12,6 +12,9 @@ >> >> #define WDT_CTRL_RESTART (0x1 << 0) >> #define WDT_CTRL_KEY (0x0a57 << 1) >> + >> +#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) >> + >> #define WDT_MODE_EN (0x1 << 0) >> #define WDT_MODE_RESET_EN (0x1 << 1) >> >> @@ -21,4 +24,21 @@ struct sunxi_wdog { >> u32 res[2]; >> }; >> >> +#else >> + >> +#define WDT_CFG_RESET (0x1) >> +#define WDT_MODE_EN (0x1) >> + >> +struct sunxi_wdog { >> + u32 irq_en; /* 0x00 */ >> + u32 irq_sta; /* 0x04 */ >> + u32 res1[2]; >> + u32 ctl; /* 0x10 */ >> + u32 cfg; /* 0x14 */ >> + u32 mode; /* 0x18 */ >> + u32 res2; >> +}; >> + >> +#endif >> + >> #endif /* _SUNXI_WATCHDOG_H_ */ > >
On Sun, 2014-10-12 at 10:40 +0800, Chen-Yu Tsai wrote: > On Sat, Oct 11, 2014 at 11:33 PM, Ian Campbell <ijc@hellion.org.uk> wrote: > > On Sat, 2014-10-04 at 20:37 +0800, Chen-Yu Tsai wrote: > >> +#else /* CONFIG_SUN6I || CONFIG_SUN8I || .. */ > >> + 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_CFG_RESET, &wdog->cfg); > >> + writel(WDT_MODE_EN, &wdog->mode); > >> + writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); > > > > That's annoyingly close to the 4/5/7i version, but not quite close > > enough to allow any meaningful sharing :-/ > > I suppose it is possible to share using clrsetbits... I think it probably isn't worth it. > > >> + while (1) { > >> + /* sun5i sometimes gets stuck without this */ > > > > Is this not therefore unnecessary on 6i/8i? > > The kernel restart driver uses this. > But Allwinner's original code does not. Unless it is needed in practice lets just leave it out. Ian.
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index b6d63db..ecf3ff9 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -75,6 +75,7 @@ int gpio_init(void) void reset_cpu(ulong addr) { +#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) static const struct sunxi_wdog *wdog = &((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog; @@ -86,6 +87,20 @@ void reset_cpu(ulong addr) /* sun5i sometimes gets stuck without this */ writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); } +#else /* CONFIG_SUN6I || CONFIG_SUN8I || .. */ + 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_CFG_RESET, &wdog->cfg); + writel(WDT_MODE_EN, &wdog->mode); + writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); + + while (1) { + /* sun5i sometimes gets stuck without this */ + writel(WDT_MODE_EN, &wdog->mode); + } +#endif } /* do some early init */ diff --git a/arch/arm/include/asm/arch-sunxi/watchdog.h b/arch/arm/include/asm/arch-sunxi/watchdog.h index 5b755e3..ccc8fa3 100644 --- a/arch/arm/include/asm/arch-sunxi/watchdog.h +++ b/arch/arm/include/asm/arch-sunxi/watchdog.h @@ -12,6 +12,9 @@ #define WDT_CTRL_RESTART (0x1 << 0) #define WDT_CTRL_KEY (0x0a57 << 1) + +#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) + #define WDT_MODE_EN (0x1 << 0) #define WDT_MODE_RESET_EN (0x1 << 1) @@ -21,4 +24,21 @@ struct sunxi_wdog { u32 res[2]; }; +#else + +#define WDT_CFG_RESET (0x1) +#define WDT_MODE_EN (0x1) + +struct sunxi_wdog { + u32 irq_en; /* 0x00 */ + u32 irq_sta; /* 0x04 */ + u32 res1[2]; + u32 ctl; /* 0x10 */ + u32 cfg; /* 0x14 */ + u32 mode; /* 0x18 */ + u32 res2; +}; + +#endif + #endif /* _SUNXI_WATCHDOG_H_ */
The watchdog on sun6i/sun8i has a different layout. Add the new layout and fix up the setup functions so that reset works. Signed-off-by: Chen-Yu Tsai <wens@csie.org> --- arch/arm/cpu/armv7/sunxi/board.c | 15 +++++++++++++++ arch/arm/include/asm/arch-sunxi/watchdog.h | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+)