1988ea355SHeiko Schocher /*
2988ea355SHeiko Schocher * omap_wdt.c
3988ea355SHeiko Schocher *
4988ea355SHeiko Schocher * (C) Copyright 2013
5988ea355SHeiko Schocher * Heiko Schocher, DENX Software Engineering, hs@denx.de.
6988ea355SHeiko Schocher *
7988ea355SHeiko Schocher * SPDX-License-Identifier: GPL-2.0
8988ea355SHeiko Schocher *
9988ea355SHeiko Schocher * Based on:
10988ea355SHeiko Schocher *
11988ea355SHeiko Schocher * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog
12988ea355SHeiko Schocher *
13988ea355SHeiko Schocher * commit 2d991a164a61858012651e13c59521975504e260
14988ea355SHeiko Schocher * Author: Bill Pemberton <wfp5p@virginia.edu>
15988ea355SHeiko Schocher * Date: Mon Nov 19 13:21:41 2012 -0500
16988ea355SHeiko Schocher *
17988ea355SHeiko Schocher * watchdog: remove use of __devinit
18988ea355SHeiko Schocher *
19988ea355SHeiko Schocher * CONFIG_HOTPLUG is going away as an option so __devinit is no longer
20988ea355SHeiko Schocher * needed.
21988ea355SHeiko Schocher *
22988ea355SHeiko Schocher * Author: MontaVista Software, Inc.
23988ea355SHeiko Schocher * <gdavis@mvista.com> or <source@mvista.com>
24988ea355SHeiko Schocher *
25988ea355SHeiko Schocher * History:
26988ea355SHeiko Schocher *
27988ea355SHeiko Schocher * 20030527: George G. Davis <gdavis@mvista.com>
28988ea355SHeiko Schocher * Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
29988ea355SHeiko Schocher * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
30988ea355SHeiko Schocher * Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk>
31988ea355SHeiko Schocher *
32988ea355SHeiko Schocher * Copyright (c) 2004 Texas Instruments.
33988ea355SHeiko Schocher * 1. Modified to support OMAP1610 32-KHz watchdog timer
34988ea355SHeiko Schocher * 2. Ported to 2.6 kernel
35988ea355SHeiko Schocher *
36988ea355SHeiko Schocher * Copyright (c) 2005 David Brownell
37988ea355SHeiko Schocher * Use the driver model and standard identifiers; handle bigger timeouts.
38988ea355SHeiko Schocher */
39988ea355SHeiko Schocher
40988ea355SHeiko Schocher #include <common.h>
41988ea355SHeiko Schocher #include <watchdog.h>
42988ea355SHeiko Schocher #include <asm/arch/hardware.h>
43988ea355SHeiko Schocher #include <asm/io.h>
44988ea355SHeiko Schocher #include <asm/processor.h>
45988ea355SHeiko Schocher #include <asm/arch/cpu.h>
46988ea355SHeiko Schocher
47988ea355SHeiko Schocher /* Hardware timeout in seconds */
48988ea355SHeiko Schocher #define WDT_HW_TIMEOUT 60
49988ea355SHeiko Schocher
50988ea355SHeiko Schocher static unsigned int wdt_trgr_pattern = 0x1234;
51988ea355SHeiko Schocher
hw_watchdog_reset(void)52988ea355SHeiko Schocher void hw_watchdog_reset(void)
53988ea355SHeiko Schocher {
54988ea355SHeiko Schocher struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
55988ea355SHeiko Schocher
56988ea355SHeiko Schocher /* wait for posted write to complete */
57988ea355SHeiko Schocher while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WTGR)
58988ea355SHeiko Schocher ;
59988ea355SHeiko Schocher
60988ea355SHeiko Schocher wdt_trgr_pattern = ~wdt_trgr_pattern;
61988ea355SHeiko Schocher writel(wdt_trgr_pattern, &wdt->wdtwtgr);
62988ea355SHeiko Schocher
63988ea355SHeiko Schocher /* wait for posted write to complete */
64988ea355SHeiko Schocher while ((readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WTGR))
65988ea355SHeiko Schocher ;
66988ea355SHeiko Schocher }
67988ea355SHeiko Schocher
omap_wdt_set_timeout(unsigned int timeout)68988ea355SHeiko Schocher static int omap_wdt_set_timeout(unsigned int timeout)
69988ea355SHeiko Schocher {
70988ea355SHeiko Schocher struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
71988ea355SHeiko Schocher u32 pre_margin = GET_WLDR_VAL(timeout);
72988ea355SHeiko Schocher
73988ea355SHeiko Schocher /* just count up at 32 KHz */
74988ea355SHeiko Schocher while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR)
75988ea355SHeiko Schocher ;
76988ea355SHeiko Schocher
77988ea355SHeiko Schocher writel(pre_margin, &wdt->wdtwldr);
78988ea355SHeiko Schocher while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR)
79988ea355SHeiko Schocher ;
80988ea355SHeiko Schocher
81988ea355SHeiko Schocher return 0;
82988ea355SHeiko Schocher }
83988ea355SHeiko Schocher
hw_watchdog_disable(void)84*b633b9c8SLukasz Majewski void hw_watchdog_disable(void)
85*b633b9c8SLukasz Majewski {
86*b633b9c8SLukasz Majewski struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
87*b633b9c8SLukasz Majewski
88*b633b9c8SLukasz Majewski /*
89*b633b9c8SLukasz Majewski * Disable watchdog
90*b633b9c8SLukasz Majewski */
91*b633b9c8SLukasz Majewski writel(0xAAAA, &wdt->wdtwspr);
92*b633b9c8SLukasz Majewski while (readl(&wdt->wdtwwps) != 0x0)
93*b633b9c8SLukasz Majewski ;
94*b633b9c8SLukasz Majewski writel(0x5555, &wdt->wdtwspr);
95*b633b9c8SLukasz Majewski while (readl(&wdt->wdtwwps) != 0x0)
96*b633b9c8SLukasz Majewski ;
97*b633b9c8SLukasz Majewski }
98*b633b9c8SLukasz Majewski
hw_watchdog_init(void)99988ea355SHeiko Schocher void hw_watchdog_init(void)
100988ea355SHeiko Schocher {
101988ea355SHeiko Schocher struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
102988ea355SHeiko Schocher
103*b633b9c8SLukasz Majewski /*
104*b633b9c8SLukasz Majewski * Make sure the watchdog is disabled. This is unfortunately required
105*b633b9c8SLukasz Majewski * because writing to various registers with the watchdog running has no
106*b633b9c8SLukasz Majewski * effect.
107*b633b9c8SLukasz Majewski */
108*b633b9c8SLukasz Majewski hw_watchdog_disable();
109*b633b9c8SLukasz Majewski
110988ea355SHeiko Schocher /* initialize prescaler */
111988ea355SHeiko Schocher while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR)
112988ea355SHeiko Schocher ;
113988ea355SHeiko Schocher
114988ea355SHeiko Schocher writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &wdt->wdtwclr);
115988ea355SHeiko Schocher while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR)
116988ea355SHeiko Schocher ;
117988ea355SHeiko Schocher
118988ea355SHeiko Schocher omap_wdt_set_timeout(WDT_HW_TIMEOUT);
119988ea355SHeiko Schocher
120988ea355SHeiko Schocher /* Sequence to enable the watchdog */
121988ea355SHeiko Schocher writel(0xBBBB, &wdt->wdtwspr);
122988ea355SHeiko Schocher while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
123988ea355SHeiko Schocher ;
124988ea355SHeiko Schocher
125988ea355SHeiko Schocher writel(0x4444, &wdt->wdtwspr);
126988ea355SHeiko Schocher while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
127988ea355SHeiko Schocher ;
128988ea355SHeiko Schocher }
129