1// SPDX-License-Identifier: GPL-2.0 2/* 3 * omap_wdt.c 4 * 5 * (C) Copyright 2013 6 * Heiko Schocher, DENX Software Engineering, hs@denx.de. 7 * 8 * Based on: 9 * 10 * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog 11 * 12 * commit 2d991a164a61858012651e13c59521975504e260 13 * Author: Bill Pemberton <wfp5p@virginia.edu> 14 * Date: Mon Nov 19 13:21:41 2012 -0500 15 * 16 * watchdog: remove use of __devinit 17 * 18 * CONFIG_HOTPLUG is going away as an option so __devinit is no longer 19 * needed. 20 * 21 * Author: MontaVista Software, Inc. 22 * <gdavis@mvista.com> or <source@mvista.com> 23 * 24 * History: 25 * 26 * 20030527: George G. Davis <gdavis@mvista.com> 27 * Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c 28 * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> 29 * Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk> 30 * 31 * Copyright (c) 2004 Texas Instruments. 32 * 1. Modified to support OMAP1610 32-KHz watchdog timer 33 * 2. Ported to 2.6 kernel 34 * 35 * Copyright (c) 2005 David Brownell 36 * Use the driver model and standard identifiers; handle bigger timeouts. 37 */ 38 39#include <log.h> 40#include <watchdog.h> 41#include <asm/ti-common/omap_wdt.h> 42#include <asm/io.h> 43#include <asm/processor.h> 44#include <asm/arch/cpu.h> 45#include <wdt.h> 46#include <dm.h> 47#include <errno.h> 48 49/* Hardware timeout in seconds */ 50#define WDT_HW_TIMEOUT 60 51 52#if !CONFIG_IS_ENABLED(WDT) 53static unsigned int wdt_trgr_pattern = 0x1234; 54 55void hw_watchdog_reset(void) 56{ 57 struct wd_timer *wdt = (struct wd_timer *)WDT_BASE; 58 59 /* 60 * Somebody just triggered watchdog reset and write to WTGR register 61 * is in progress. It is resetting right now, no need to trigger it 62 * again 63 */ 64 if ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WTGR) 65 return; 66 67 wdt_trgr_pattern = ~wdt_trgr_pattern; 68 writel(wdt_trgr_pattern, &wdt->wdtwtgr); 69 70 /* 71 * Don't wait for posted write to complete, i.e. don't check 72 * WDT_WWPS_PEND_WTGR bit in WWPS register. There is no writes to 73 * WTGR register outside of this func, and if entering it 74 * we see WDT_WWPS_PEND_WTGR bit set, it means watchdog reset 75 * was just triggered. This prevents us from wasting time in busy 76 * polling of WDT_WWPS_PEND_WTGR bit. 77 */ 78} 79 80static int omap_wdt_set_timeout(unsigned int timeout) 81{ 82 struct wd_timer *wdt = (struct wd_timer *)WDT_BASE; 83 u32 pre_margin = GET_WLDR_VAL(timeout); 84 85 /* just count up at 32 KHz */ 86 while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR) 87 ; 88 89 writel(pre_margin, &wdt->wdtwldr); 90 while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR) 91 ; 92 93 return 0; 94} 95 96void hw_watchdog_disable(void) 97{ 98 struct wd_timer *wdt = (struct wd_timer *)WDT_BASE; 99 100 /* 101 * Disable watchdog 102 */ 103 writel(0xAAAA, &wdt->wdtwspr); 104 while (readl(&wdt->wdtwwps) != 0x0) 105 ; 106 writel(0x5555, &wdt->wdtwspr); 107 while (readl(&wdt->wdtwwps) != 0x0) 108 ; 109} 110 111void hw_watchdog_init(void) 112{ 113 struct wd_timer *wdt = (struct wd_timer *)WDT_BASE; 114 115 /* 116 * Make sure the watchdog is disabled. This is unfortunately required 117 * because writing to various registers with the watchdog running has no 118 * effect. 119 */ 120 hw_watchdog_disable(); 121 122 /* initialize prescaler */ 123 while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR) 124 ; 125 126 writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &wdt->wdtwclr); 127 while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR) 128 ; 129 130 omap_wdt_set_timeout(WDT_HW_TIMEOUT); 131 132 /* Sequence to enable the watchdog */ 133 writel(0xBBBB, &wdt->wdtwspr); 134 while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR) 135 ; 136 137 writel(0x4444, &wdt->wdtwspr); 138 while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR) 139 ; 140} 141 142void watchdog_reset(void) 143{ 144 hw_watchdog_reset(); 145} 146 147#else 148 149static int omap3_wdt_reset(struct udevice *dev) 150{ 151 struct omap3_wdt_priv *priv = dev_get_priv(dev); 152 153 /* 154 * Somebody just triggered watchdog reset and write to WTGR register 155 * is in progress. It is resetting right now, no need to trigger it 156 * again 157 */ 158 if ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR) 159 return 0; 160 161 priv->wdt_trgr_pattern = ~(priv->wdt_trgr_pattern); 162 writel(priv->wdt_trgr_pattern, &priv->regs->wdtwtgr); 163 /* 164 * Don't wait for posted write to complete, i.e. don't check 165 * WDT_WWPS_PEND_WTGR bit in WWPS register. There is no writes to 166 * WTGR register outside of this func, and if entering it 167 * we see WDT_WWPS_PEND_WTGR bit set, it means watchdog reset 168 * was just triggered. This prevents us from wasting time in busy 169 * polling of WDT_WWPS_PEND_WTGR bit. 170 */ 171 return 0; 172} 173 174static int omap3_wdt_stop(struct udevice *dev) 175{ 176 struct omap3_wdt_priv *priv = dev_get_priv(dev); 177 178 /* disable watchdog */ 179 writel(0xAAAA, &priv->regs->wdtwspr); 180 while (readl(&priv->regs->wdtwwps) != 0x0) 181 ; 182 writel(0x5555, &priv->regs->wdtwspr); 183 while (readl(&priv->regs->wdtwwps) != 0x0) 184 ; 185 return 0; 186} 187 188static int omap3_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) 189{ 190 struct omap3_wdt_priv *priv = dev_get_priv(dev); 191 u32 pre_margin = GET_WLDR_VAL(timeout_ms / 1000); 192 /* 193 * Make sure the watchdog is disabled. This is unfortunately required 194 * because writing to various registers with the watchdog running has 195 * no effect. 196 */ 197 omap3_wdt_stop(dev); 198 199 /* initialize prescaler */ 200 while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR) 201 ; 202 203 writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &priv->regs->wdtwclr); 204 while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR) 205 ; 206 /* just count up at 32 KHz */ 207 while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR) 208 ; 209 210 writel(pre_margin, &priv->regs->wdtwldr); 211 while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR) 212 ; 213 /* Sequence to enable the watchdog */ 214 writel(0xBBBB, &priv->regs->wdtwspr); 215 while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR) 216 ; 217 218 writel(0x4444, &priv->regs->wdtwspr); 219 while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR) 220 ; 221 222 /* Trigger the watchdog to actually reload the counter. */ 223 while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR) 224 ; 225 226 priv->wdt_trgr_pattern = ~(priv->wdt_trgr_pattern); 227 writel(priv->wdt_trgr_pattern, &priv->regs->wdtwtgr); 228 229 while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR) 230 ; 231 232 return 0; 233} 234 235static int omap3_wdt_probe(struct udevice *dev) 236{ 237 struct omap3_wdt_priv *priv = dev_get_priv(dev); 238 239 priv->regs = dev_read_addr_ptr(dev); 240 if (!priv->regs) 241 return -EINVAL; 242 243 priv->wdt_trgr_pattern = 0x1234; 244 debug("%s: Probing wdt%u\n", __func__, dev_seq(dev)); 245 return 0; 246} 247 248static const struct wdt_ops omap3_wdt_ops = { 249 .start = omap3_wdt_start, 250 .stop = omap3_wdt_stop, 251 .reset = omap3_wdt_reset, 252}; 253 254static const struct udevice_id omap3_wdt_ids[] = { 255 { .compatible = "ti,omap3-wdt" }, 256 { } 257}; 258 259U_BOOT_DRIVER(omap3_wdt) = { 260 .name = "omap3_wdt", 261 .id = UCLASS_WDT, 262 .of_match = omap3_wdt_ids, 263 .ops = &omap3_wdt_ops, 264 .probe = omap3_wdt_probe, 265 .priv_auto = sizeof(struct omap3_wdt_priv), 266}; 267#endif /* !CONFIG_IS_ENABLED(WDT) */ 268