diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2015-08-28 09:58:54 +0800 |
---|---|---|
committer | Yang Zhang <yang.z.zhang@intel.com> | 2015-09-01 12:44:00 +0800 |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/drivers/watchdog | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/drivers/watchdog')
-rw-r--r-- | qemu/roms/u-boot/drivers/watchdog/Makefile | 17 | ||||
-rw-r--r-- | qemu/roms/u-boot/drivers/watchdog/at91sam9_wdt.c | 77 | ||||
-rw-r--r-- | qemu/roms/u-boot/drivers/watchdog/bfin_wdt.c | 26 | ||||
-rw-r--r-- | qemu/roms/u-boot/drivers/watchdog/ftwdt010_wdt.c | 92 | ||||
-rw-r--r-- | qemu/roms/u-boot/drivers/watchdog/imx_watchdog.c | 67 | ||||
-rw-r--r-- | qemu/roms/u-boot/drivers/watchdog/omap_wdt.c | 121 | ||||
-rw-r--r-- | qemu/roms/u-boot/drivers/watchdog/s5p_wdt.c | 43 | ||||
-rw-r--r-- | qemu/roms/u-boot/drivers/watchdog/tnetv107x_wdt.c | 165 | ||||
-rw-r--r-- | qemu/roms/u-boot/drivers/watchdog/xilinx_tb_wdt.c | 69 |
9 files changed, 677 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/drivers/watchdog/Makefile b/qemu/roms/u-boot/drivers/watchdog/Makefile new file mode 100644 index 000000000..06ced10c3 --- /dev/null +++ b/qemu/roms/u-boot/drivers/watchdog/Makefile @@ -0,0 +1,17 @@ +# +# (C) Copyright 2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_AT91SAM9_WATCHDOG) += at91sam9_wdt.o +obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o +ifneq (,$(filter $(SOC), mx31 mx35 mx5 mx6 vf610)) +obj-y += imx_watchdog.o +endif +obj-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o +obj-$(CONFIG_S5P) += s5p_wdt.o +obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o +obj-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o +obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o diff --git a/qemu/roms/u-boot/drivers/watchdog/at91sam9_wdt.c b/qemu/roms/u-boot/drivers/watchdog/at91sam9_wdt.c new file mode 100644 index 000000000..ffd49a2be --- /dev/null +++ b/qemu/roms/u-boot/drivers/watchdog/at91sam9_wdt.c @@ -0,0 +1,77 @@ +/* + * [origin: Linux kernel drivers/watchdog/at91sam9_wdt.c] + * + * Watchdog driver for Atmel AT91SAM9x processors. + * + * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * Copyright (C) 2008 Renaud CERRATO r.cerrato@til-technologies.fr + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * The Watchdog Timer Mode Register can be only written to once. If the + * timeout need to be set from U-Boot, be sure that the bootstrap doesn't + * write to this register. Inform Linux to it too + */ + +#include <common.h> +#include <watchdog.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> +#include <asm/arch/at91_wdt.h> + +/* + * AT91SAM9 watchdog runs a 12bit counter @ 256Hz, + * use this to convert a watchdog + * value from/to milliseconds. + */ +#define ms_to_ticks(t) (((t << 8) / 1000) - 1) +#define ticks_to_ms(t) (((t + 1) * 1000) >> 8) + +/* Hardware timeout in seconds */ +#define WDT_HW_TIMEOUT 2 + +/* + * Set the watchdog time interval in 1/256Hz (write-once) + * Counter is 12 bit. + */ +static int at91_wdt_settimeout(unsigned int timeout) +{ + unsigned int reg; + at91_wdt_t *wd = (at91_wdt_t *) ATMEL_BASE_WDT; + + /* Check if disabled */ + if (readl(&wd->mr) & AT91_WDT_MR_WDDIS) { + printf("sorry, watchdog is disabled\n"); + return -1; + } + + /* + * All counting occurs at SLOW_CLOCK / 128 = 256 Hz + * + * Since WDV is a 12-bit counter, the maximum period is + * 4096 / 256 = 16 seconds. + */ + + reg = AT91_WDT_MR_WDRSTEN /* causes watchdog reset */ + | AT91_WDT_MR_WDDBGHLT /* disabled in debug mode */ + | AT91_WDT_MR_WDD(0xfff) /* restart at any time */ + | AT91_WDT_MR_WDV(timeout); /* timer value */ + + writel(reg, &wd->mr); + + return 0; +} + +void hw_watchdog_reset(void) +{ + at91_wdt_t *wd = (at91_wdt_t *) ATMEL_BASE_WDT; + writel(AT91_WDT_CR_WDRSTT | AT91_WDT_CR_KEY, &wd->cr); +} + +void hw_watchdog_init(void) +{ + /* 16 seconds timer, resets enabled */ + at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000)); +} diff --git a/qemu/roms/u-boot/drivers/watchdog/bfin_wdt.c b/qemu/roms/u-boot/drivers/watchdog/bfin_wdt.c new file mode 100644 index 000000000..7a6756b2e --- /dev/null +++ b/qemu/roms/u-boot/drivers/watchdog/bfin_wdt.c @@ -0,0 +1,26 @@ +/* + * watchdog.c - driver for Blackfin on-chip watchdog + * + * Copyright (c) 2007-2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <watchdog.h> +#include <asm/blackfin.h> +#include <asm/mach-common/bits/watchdog.h> + +void hw_watchdog_reset(void) +{ + bfin_write_WDOG_STAT(0); +} + +void hw_watchdog_init(void) +{ + bfin_write_WDOG_CTL(WDDIS); + SSYNC(); + bfin_write_WDOG_CNT(CONFIG_WATCHDOG_TIMEOUT_MSECS / 1000 * get_sclk()); + hw_watchdog_reset(); + bfin_write_WDOG_CTL(WDEN); +} diff --git a/qemu/roms/u-boot/drivers/watchdog/ftwdt010_wdt.c b/qemu/roms/u-boot/drivers/watchdog/ftwdt010_wdt.c new file mode 100644 index 000000000..11f58f529 --- /dev/null +++ b/qemu/roms/u-boot/drivers/watchdog/ftwdt010_wdt.c @@ -0,0 +1,92 @@ +/* + * Watchdog driver for the FTWDT010 Watch Dog Driver + * + * (c) Copyright 2004 Faraday Technology Corp. (www.faraday-tech.com) + * Based on sa1100_wdt.c by Oleg Drokin <green@crimea.edu> + * Based on SoftDog driver by Alan Cox <alan@redhat.com> + * + * Copyright (C) 2011 Andes Technology Corporation + * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 27/11/2004 Initial release, Faraday. + * 12/01/2011 Port to u-boot, Macpaul Lin. + */ + +#include <common.h> +#include <watchdog.h> +#include <asm/io.h> +#include <faraday/ftwdt010_wdt.h> + +/* + * Set the watchdog time interval. + * Counter is 32 bit. + */ +int ftwdt010_wdt_settimeout(unsigned int timeout) +{ + unsigned int reg; + + struct ftwdt010_wdt *wd = (struct ftwdt010_wdt *)CONFIG_FTWDT010_BASE; + + debug("Activating WDT..\n"); + + /* Check if disabled */ + if (readl(&wd->wdcr) & ~FTWDT010_WDCR_ENABLE) { + printf("sorry, watchdog is disabled\n"); + return -1; + } + + /* + * In a 66MHz system, + * if you set WDLOAD as 0x03EF1480 (66000000) + * the reset timer is 1 second. + */ + reg = FTWDT010_WDLOAD(timeout * FTWDT010_TIMEOUT_FACTOR); + + writel(reg, &wd->wdload); + + return 0; +} + +void ftwdt010_wdt_reset(void) +{ + struct ftwdt010_wdt *wd = (struct ftwdt010_wdt *)CONFIG_FTWDT010_BASE; + + /* clear control register */ + writel(0, &wd->wdcr); + + /* Write Magic number */ + writel(FTWDT010_WDRESTART_MAGIC, &wd->wdrestart); + + /* Enable WDT */ + writel((FTWDT010_WDCR_RST | FTWDT010_WDCR_ENABLE), &wd->wdcr); +} + +void ftwdt010_wdt_disable(void) +{ + struct ftwdt010_wdt *wd = (struct ftwdt010_wdt *)CONFIG_FTWDT010_BASE; + + debug("Deactivating WDT..\n"); + + /* + * It was defined with CONFIG_WATCHDOG_NOWAYOUT in Linux + * + * Shut off the timer. + * Lock it in if it's a module and we defined ...NOWAYOUT + */ + writel(0, &wd->wdcr); +} + +#if defined(CONFIG_HW_WATCHDOG) +void hw_watchdog_reset(void) +{ + ftwdt010_wdt_reset(); +} + +void hw_watchdog_init(void) +{ + /* set timer in ms */ + ftwdt010_wdt_settimeout(CONFIG_FTWDT010_HW_TIMEOUT * 1000); +} +#endif diff --git a/qemu/roms/u-boot/drivers/watchdog/imx_watchdog.c b/qemu/roms/u-boot/drivers/watchdog/imx_watchdog.c new file mode 100644 index 000000000..d5993b4d2 --- /dev/null +++ b/qemu/roms/u-boot/drivers/watchdog/imx_watchdog.c @@ -0,0 +1,67 @@ +/* + * watchdog.c - driver for i.mx on-chip watchdog + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <asm/io.h> +#include <watchdog.h> +#include <asm/arch/imx-regs.h> + +struct watchdog_regs { + u16 wcr; /* Control */ + u16 wsr; /* Service */ + u16 wrsr; /* Reset Status */ +}; + +#define WCR_WDZST 0x01 +#define WCR_WDBG 0x02 +#define WCR_WDE 0x04 /* WDOG enable */ +#define WCR_WDT 0x08 +#define WCR_SRS 0x10 +#define WCR_WDW 0x80 +#define SET_WCR_WT(x) (x << 8) + +#ifdef CONFIG_IMX_WATCHDOG +void hw_watchdog_reset(void) +{ + struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; + + writew(0x5555, &wdog->wsr); + writew(0xaaaa, &wdog->wsr); +} + +void hw_watchdog_init(void) +{ + struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; + u16 timeout; + + /* + * The timer watchdog can be set between + * 0.5 and 128 Seconds. If not defined + * in configuration file, sets 128 Seconds + */ +#ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS +#define CONFIG_WATCHDOG_TIMEOUT_MSECS 128000 +#endif + timeout = (CONFIG_WATCHDOG_TIMEOUT_MSECS / 500) - 1; + writew(WCR_WDZST | WCR_WDBG | WCR_WDE | WCR_WDT | WCR_SRS | + WCR_WDW | SET_WCR_WT(timeout), &wdog->wcr); + hw_watchdog_reset(); +} +#endif + +void reset_cpu(ulong addr) +{ + struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; + + writew(WCR_WDE, &wdog->wcr); + writew(0x5555, &wdog->wsr); + writew(0xaaaa, &wdog->wsr); /* load minimum 1/2 second timeout */ + while (1) { + /* + * spin for .5 seconds before reset + */ + } +} diff --git a/qemu/roms/u-boot/drivers/watchdog/omap_wdt.c b/qemu/roms/u-boot/drivers/watchdog/omap_wdt.c new file mode 100644 index 000000000..7ea4b604c --- /dev/null +++ b/qemu/roms/u-boot/drivers/watchdog/omap_wdt.c @@ -0,0 +1,121 @@ +/* + * omap_wdt.c + * + * (C) Copyright 2013 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * SPDX-License-Identifier: GPL-2.0 + * + * Based on: + * + * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog + * + * commit 2d991a164a61858012651e13c59521975504e260 + * Author: Bill Pemberton <wfp5p@virginia.edu> + * Date: Mon Nov 19 13:21:41 2012 -0500 + * + * watchdog: remove use of __devinit + * + * CONFIG_HOTPLUG is going away as an option so __devinit is no longer + * needed. + * + * Author: MontaVista Software, Inc. + * <gdavis@mvista.com> or <source@mvista.com> + * + * History: + * + * 20030527: George G. Davis <gdavis@mvista.com> + * Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> + * Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk> + * + * Copyright (c) 2004 Texas Instruments. + * 1. Modified to support OMAP1610 32-KHz watchdog timer + * 2. Ported to 2.6 kernel + * + * Copyright (c) 2005 David Brownell + * Use the driver model and standard identifiers; handle bigger timeouts. + */ + +#include <common.h> +#include <watchdog.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/arch/cpu.h> + +/* Hardware timeout in seconds */ +#define WDT_HW_TIMEOUT 60 + +static unsigned int wdt_trgr_pattern = 0x1234; + +void hw_watchdog_reset(void) +{ + struct wd_timer *wdt = (struct wd_timer *)WDT_BASE; + + /* wait for posted write to complete */ + while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WTGR) + ; + + wdt_trgr_pattern = ~wdt_trgr_pattern; + writel(wdt_trgr_pattern, &wdt->wdtwtgr); + + /* wait for posted write to complete */ + while ((readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WTGR)) + ; +} + +static int omap_wdt_set_timeout(unsigned int timeout) +{ + struct wd_timer *wdt = (struct wd_timer *)WDT_BASE; + u32 pre_margin = GET_WLDR_VAL(timeout); + + /* just count up at 32 KHz */ + while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR) + ; + + writel(pre_margin, &wdt->wdtwldr); + while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR) + ; + + return 0; +} + +void hw_watchdog_init(void) +{ + struct wd_timer *wdt = (struct wd_timer *)WDT_BASE; + + /* initialize prescaler */ + while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR) + ; + + writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &wdt->wdtwclr); + while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR) + ; + + omap_wdt_set_timeout(WDT_HW_TIMEOUT); + + /* Sequence to enable the watchdog */ + writel(0xBBBB, &wdt->wdtwspr); + while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR) + ; + + writel(0x4444, &wdt->wdtwspr); + while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR) + ; +} + +void hw_watchdog_disable(void) +{ + struct wd_timer *wdt = (struct wd_timer *)WDT_BASE; + + /* + * Disable watchdog + */ + writel(0xAAAA, &wdt->wdtwspr); + while (readl(&wdt->wdtwwps) != 0x0) + ; + writel(0x5555, &wdt->wdtwspr); + while (readl(&wdt->wdtwwps) != 0x0) + ; +} diff --git a/qemu/roms/u-boot/drivers/watchdog/s5p_wdt.c b/qemu/roms/u-boot/drivers/watchdog/s5p_wdt.c new file mode 100644 index 000000000..a6e54d9f7 --- /dev/null +++ b/qemu/roms/u-boot/drivers/watchdog/s5p_wdt.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * Minkyu Kang <mk7.kang@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/watchdog.h> + +#define PRESCALER_VAL 255 + +void wdt_stop(void) +{ + struct s5p_watchdog *wdt = + (struct s5p_watchdog *)samsung_get_base_watchdog(); + unsigned int wtcon; + + wtcon = readl(&wdt->wtcon); + wtcon &= ~(WTCON_EN | WTCON_INT | WTCON_RESET); + + writel(wtcon, &wdt->wtcon); +} + +void wdt_start(unsigned int timeout) +{ + struct s5p_watchdog *wdt = + (struct s5p_watchdog *)samsung_get_base_watchdog(); + unsigned int wtcon; + + wdt_stop(); + + wtcon = readl(&wdt->wtcon); + wtcon |= (WTCON_EN | WTCON_CLK(WTCON_CLK_128)); + wtcon &= ~WTCON_INT; + wtcon |= WTCON_RESET; + wtcon |= WTCON_PRESCALER(PRESCALER_VAL); + + writel(timeout, &wdt->wtdat); + writel(timeout, &wdt->wtcnt); + writel(wtcon, &wdt->wtcon); +} diff --git a/qemu/roms/u-boot/drivers/watchdog/tnetv107x_wdt.c b/qemu/roms/u-boot/drivers/watchdog/tnetv107x_wdt.c new file mode 100644 index 000000000..3d3f366c0 --- /dev/null +++ b/qemu/roms/u-boot/drivers/watchdog/tnetv107x_wdt.c @@ -0,0 +1,165 @@ +/* + * TNETV107X: Watchdog timer implementation (for reset) + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> + +#define MAX_DIV 0xFFFE0001 + +struct wdt_regs { + u32 kick_lock; +#define KICK_LOCK_1 0x5555 +#define KICK_LOCK_2 0xaaaa + u32 kick; + + u32 change_lock; +#define CHANGE_LOCK_1 0x6666 +#define CHANGE_LOCK_2 0xbbbb + u32 change; + + u32 disable_lock; +#define DISABLE_LOCK_1 0x7777 +#define DISABLE_LOCK_2 0xcccc +#define DISABLE_LOCK_3 0xdddd + u32 disable; + + u32 prescale_lock; +#define PRESCALE_LOCK_1 0x5a5a +#define PRESCALE_LOCK_2 0xa5a5 + u32 prescale; +}; + +static struct wdt_regs* regs = (struct wdt_regs *)TNETV107X_WDT0_ARM_BASE; + +#define wdt_reg_read(reg) __raw_readl(®s->reg) +#define wdt_reg_write(reg, val) __raw_writel((val), ®s->reg) + +static int write_prescale_reg(unsigned long prescale_value) +{ + wdt_reg_write(prescale_lock, PRESCALE_LOCK_1); + if ((wdt_reg_read(prescale_lock) & 0x3) != 0x1) + return -1; + + wdt_reg_write(prescale_lock, PRESCALE_LOCK_2); + if ((wdt_reg_read(prescale_lock) & 0x3) != 0x3) + return -1; + + wdt_reg_write(prescale, prescale_value); + + return 0; +} + +static int write_change_reg(unsigned long initial_timer_value) +{ + wdt_reg_write(change_lock, CHANGE_LOCK_1); + if ((wdt_reg_read(change_lock) & 0x3) != 0x1) + return -1; + + wdt_reg_write(change_lock, CHANGE_LOCK_2); + if ((wdt_reg_read(change_lock) & 0x3) != 0x3) + return -1; + + wdt_reg_write(change, initial_timer_value); + + return 0; +} + +static int wdt_control(unsigned long disable_value) +{ + wdt_reg_write(disable_lock, DISABLE_LOCK_1); + if ((wdt_reg_read(disable_lock) & 0x3) != 0x1) + return -1; + + wdt_reg_write(disable_lock, DISABLE_LOCK_2); + if ((wdt_reg_read(disable_lock) & 0x3) != 0x2) + return -1; + + wdt_reg_write(disable_lock, DISABLE_LOCK_3); + if ((wdt_reg_read(disable_lock) & 0x3) != 0x3) + return -1; + + wdt_reg_write(disable, disable_value); + return 0; +} + +static int wdt_set_period(unsigned long msec) +{ + unsigned long change_value, count_value; + unsigned long prescale_value = 1; + unsigned long refclk_khz, maxdiv; + int ret; + + refclk_khz = clk_get_rate(TNETV107X_LPSC_WDT_ARM); + maxdiv = (MAX_DIV / refclk_khz); + + if ((!msec) || (msec > maxdiv)) + return -1; + + count_value = refclk_khz * msec; + if (count_value > 0xffff) { + change_value = count_value / 0xffff + 1; + prescale_value = count_value / change_value; + } else { + change_value = count_value; + } + + ret = write_prescale_reg(prescale_value - 1); + if (ret) + return ret; + + ret = write_change_reg(change_value); + if (ret) + return ret; + + return 0; +} + +unsigned long last_wdt = -1; + +int wdt_start(unsigned long msecs) +{ + int ret; + ret = wdt_control(0); + if (ret) + return ret; + ret = wdt_set_period(msecs); + if (ret) + return ret; + ret = wdt_control(1); + if (ret) + return ret; + ret = wdt_kick(); + last_wdt = msecs; + return ret; +} + +int wdt_stop(void) +{ + last_wdt = -1; + return wdt_control(0); +} + +int wdt_kick(void) +{ + wdt_reg_write(kick_lock, KICK_LOCK_1); + if ((wdt_reg_read(kick_lock) & 0x3) != 0x1) + return -1; + + wdt_reg_write(kick_lock, KICK_LOCK_2); + if ((wdt_reg_read(kick_lock) & 0x3) != 0x3) + return -1; + + wdt_reg_write(kick, 1); + return 0; +} + +void reset_cpu(ulong addr) +{ + clk_enable(TNETV107X_LPSC_WDT_ARM); + wdt_start(1); + wdt_kick(); +} diff --git a/qemu/roms/u-boot/drivers/watchdog/xilinx_tb_wdt.c b/qemu/roms/u-boot/drivers/watchdog/xilinx_tb_wdt.c new file mode 100644 index 000000000..6336c9488 --- /dev/null +++ b/qemu/roms/u-boot/drivers/watchdog/xilinx_tb_wdt.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011-2013 Xilinx Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/microblaze_intc.h> +#include <asm/processor.h> +#include <watchdog.h> + +#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 */ +}; + +static struct watchdog_regs *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(); +} + +void 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) + puts("Watchdog IRQ registration failed."); +} |