From: Michal Simek Date: Fri, 25 Jan 2013 13:41:04 +0000 (+0100) Subject: watchdog: Rewrite microblaze watchdog implementation X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fee10921f4e64605677583a48f0a3336ff28d45f;p=thirdparty%2Fu-boot.git watchdog: Rewrite microblaze watchdog implementation - Move watchdog to drivers/watchdog - Update documentation - Change watchdog initialization (here is small problem because watchdog uses IRQ that's why must be initialized after intc initialization - which can be problematic in cases where problem happen between start and watchdog init) - Rewrite to u-boot coding style - Disable watchdog in reset function Signed-off-by: Michal Simek --- diff --git a/arch/microblaze/cpu/Makefile b/arch/microblaze/cpu/Makefile index 350eb709873..1c169dd4bf2 100644 --- a/arch/microblaze/cpu/Makefile +++ b/arch/microblaze/cpu/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)lib$(CPU).o START = start.o SOBJS = irq.o -COBJS = cpu.o interrupts.o cache.o exception.o timer.o hw_watchdog.o +COBJS = cpu.o interrupts.o cache.o exception.o timer.o SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/arch/microblaze/cpu/hw_watchdog.c b/arch/microblaze/cpu/hw_watchdog.c deleted file mode 100644 index e5768b2f608..00000000000 --- a/arch/microblaze/cpu/hw_watchdog.c +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************** -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* (c) Copyright 2011 Xilinx Inc. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 675 Mass Ave, Cambridge, MA 02139, USA. -* -******************************************************************************/ - -#include -#include -#include - -#ifdef CONFIG_HW_WATCHDOG - - #define XWT_TWCSR0_OFFSET 0x0 /**< Control/Status Register 0 Offset */ - #define XWT_TWCSR1_OFFSET 0x4 /**< Control/Status Register 1 Offset */ - #define XWT_TBR_OFFSET 0x8 /**< Timebase Register Offset */ - - #define XWT_CSR0_WRS_MASK 0x00000008 /**< Reset status Mask */ - #define XWT_CSR0_WDS_MASK 0x00000004 /**< Timer state Mask */ - #define XWT_CSR0_EWDT1_MASK 0x00000002 /**< Enable bit 1 Mask*/ - #define XWT_CSRX_EWDT2_MASK 0x00000001 /**< Enable bit 2 Mask */ - -void hw_watchdog_reset(void) -{ - unsigned int CSRRegister; - -#ifdef XPAR_MICROBLAZE_USE_DCACHE - microblaze_invalidate_dcache_range(WATCHDOG_BASEADDR, 4); -#endif - - /* Read the current contents of TCSR0 */ - CSRRegister = inl(WATCHDOG_BASEADDR + XWT_TWCSR0_OFFSET); - - /* Clear the watchdog WDS bit */ - if (CSRRegister & (XWT_CSR0_EWDT1_MASK | XWT_CSRX_EWDT2_MASK)) - { - outl(CSRRegister | XWT_CSR0_WDS_MASK, WATCHDOG_BASEADDR + XWT_TWCSR0_OFFSET); -#ifdef XPAR_MICROBLAZE_USE_DCACHE - microblaze_flush_dcache_range(WATCHDOG_BASEADDR, 4); -#endif - } -} - -void hw_watchdog_init(void) -{ - outl((XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK | XWT_CSR0_EWDT1_MASK), WATCHDOG_BASEADDR + XWT_TWCSR0_OFFSET); - outl(XWT_CSRX_EWDT2_MASK, WATCHDOG_BASEADDR + XWT_TWCSR1_OFFSET); - -#ifdef XPAR_MICROBLAZE_USE_DCACHE - microblaze_flush_dcache_range(WATCHDOG_BASEADDR, 8); -#endif -} - -void hw_watchdog_disable(void) -{ - unsigned int CSRRegister; - -#ifdef XPAR_MICROBLAZE_USE_DCACHE - microblaze_invalidate_dcache_range(WATCHDOG_BASEADDR, 4); -#endif - - /* Read the current contents of TCSR0 */ - CSRRegister = inl(WATCHDOG_BASEADDR + XWT_TWCSR0_OFFSET); - - outl(CSRRegister & ~XWT_CSR0_EWDT1_MASK, WATCHDOG_BASEADDR + XWT_TWCSR0_OFFSET); - outl(~XWT_CSRX_EWDT2_MASK, WATCHDOG_BASEADDR + XWT_TWCSR1_OFFSET); -#ifdef XPAR_MICROBLAZE_USE_DCACHE - microblaze_flush_dcache_range(WATCHDOG_BASEADDR, 8); -#endif - -} - -#endif diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index 2c4d5ffc5cb..9d19ddaec12 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h @@ -31,4 +31,8 @@ extern char __text_start[]; /* Microblaze board initialization function */ void board_init(void); +/* Watchdog functions */ +int hw_watchdog_init(void); +void hw_watchdog_disable(void); + #endif /* __ASM_MICROBLAZE_PROCESSOR_H */ diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c index a6a8d194b72..815fb5a0c95 100644 --- a/arch/microblaze/lib/board.c +++ b/arch/microblaze/lib/board.c @@ -39,10 +39,6 @@ DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_HW_WATCHDOG) -extern int hw_watchdog_init(void); -#endif /* CONFIG_WATCHDOG */ - /* * All attempts to come up with a "common" initialization sequence * that works for all boards and architectures failed: some of the @@ -65,6 +61,9 @@ init_fnc_t *init_sequence[] = { serial_init, console_init_f, interrupts_init, +#ifdef CONFIG_XILINX_TB_WATCHDOG + hw_watchdog_init, +#endif timer_init, NULL, }; @@ -113,10 +112,6 @@ void board_init_f(ulong not_used) serial_initialize(); -#if defined(CONFIG_HW_WATCHDOG) - hw_watchdog_init(); -#endif - for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { WATCHDOG_RESET (); if ((*init_fnc_ptr) () != 0) { diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c index dc4497fe006..81b2881d6e5 100644 --- a/board/xilinx/microblaze-generic/microblaze-generic.c +++ b/board/xilinx/microblaze-generic/microblaze-generic.c @@ -39,6 +39,10 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ++(*((u32 volatile *)(CONFIG_SYS_GPIO_0_ADDR))); #endif +#ifdef CONFIG_XILINX_TB_WATCHDOG + hw_watchdog_disable(); +#endif + puts ("Reseting board\n"); __asm__ __volatile__ (" mts rmsr, r0;" \ "bra r0"); diff --git a/doc/README.watchdog b/doc/README.watchdog index ee65008b4be..33f31c21405 100644 --- a/doc/README.watchdog +++ b/doc/README.watchdog @@ -27,3 +27,6 @@ CONFIG_IMX_WATCHDOG Available for i.mx31/35/5x/6x to service the watchdog. This is not automatically set because some boards (vision2) still need to define their own hw_watchdog_reset routine. + +CONFIG_XILINX_TB_WATCHDOG + Available for Xilinx Axi platforms to service timebase watchdog timer. diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index b1f4e0f03f8..13e7c376861 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -32,6 +32,7 @@ COBJS-y += imx_watchdog.o endif COBJS-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o COBJS-$(CONFIG_S5P) += s5p_wdt.o +COBJS-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/watchdog/xilinx_tb_wdt.c b/drivers/watchdog/xilinx_tb_wdt.c new file mode 100644 index 00000000000..96caa073b92 --- /dev/null +++ b/drivers/watchdog/xilinx_tb_wdt.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011-2013 Xilinx Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#define XWT_CSR0_WRS_MASK 0x00000008 /* Reset status Mask */ +#define XWT_CSR0_WDS_MASK 0x00000004 /* Timer state Mask */ +#define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 Mask*/ +#define XWT_CSRX_EWDT2_MASK 0x00000001 /* Enable bit 2 Mask */ + +struct watchdog_regs { + u32 twcsr0; /* 0x0 */ + u32 twcsr1; /* 0x4 */ + u32 tbr; /* 0x8 */ +}; + +#define watchdog_base ((struct watchdog_regs *) CONFIG_WATCHDOG_BASEADDR) + +void hw_watchdog_reset(void) +{ + u32 reg; + + /* Read the current contents of TCSR0 */ + reg = readl(&watchdog_base->twcsr0); + + /* Clear the watchdog WDS bit */ + if (reg & (XWT_CSR0_EWDT1_MASK | XWT_CSRX_EWDT2_MASK)) { + writel(reg | XWT_CSR0_WDS_MASK, &watchdog_base->twcsr0); + } +} + +void hw_watchdog_disable(void) +{ + u32 reg; + + /* Read the current contents of TCSR0 */ + reg = readl(&watchdog_base->twcsr0); + + writel(reg & ~XWT_CSR0_EWDT1_MASK, &watchdog_base->twcsr0); + writel(~XWT_CSRX_EWDT2_MASK, &watchdog_base->twcsr1); + + puts("Watchdog disabled!\n"); +} + +static void hw_watchdog_isr(void *arg) +{ + hw_watchdog_reset(); +} + +int hw_watchdog_init(void) +{ + int ret; + + writel((XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK | XWT_CSR0_EWDT1_MASK), + &watchdog_base->twcsr0); + writel(XWT_CSRX_EWDT2_MASK, &watchdog_base->twcsr1); + + ret = install_interrupt_handler(CONFIG_WATCHDOG_IRQ, + hw_watchdog_isr, NULL); + if (ret) + return 1; + + return 0; +} diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h index dfeb8aebeec..5657582ead0 100644 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@ -140,6 +140,13 @@ # error Please setup TIMER in BSP #endif +#if defined(XILINX_WATCHDOG_BASEADDR) && defined(XILINX_WATCHDOG_IRQ) +# define CONFIG_WATCHDOG_BASEADDR XILINX_WATCHDOG_BASEADDR +# define CONFIG_WATCHDOG_IRQ XILINX_WATCHDOG_IRQ +# define CONFIG_HW_WATCHDOG 1 +# define CONFIG_XILINX_TB_WATCHDOG 1 +#endif + /* * memory layout - Example * TEXT_BASE = 0x1200_0000;