1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
29096963cSMacpaul Lin /*
39096963cSMacpaul Lin  * Watchdog driver for the FTWDT010 Watch Dog Driver
49096963cSMacpaul Lin  *
59096963cSMacpaul Lin  * (c) Copyright 2004 Faraday Technology Corp. (www.faraday-tech.com)
69096963cSMacpaul Lin  * Based on sa1100_wdt.c by Oleg Drokin <green@crimea.edu>
79096963cSMacpaul Lin  * Based on SoftDog driver by Alan Cox <alan@redhat.com>
89096963cSMacpaul Lin  *
99096963cSMacpaul Lin  * Copyright (C) 2011 Andes Technology Corporation
109096963cSMacpaul Lin  * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
119096963cSMacpaul Lin  *
129096963cSMacpaul Lin  * 27/11/2004 Initial release, Faraday.
139096963cSMacpaul Lin  * 12/01/2011 Port to u-boot, Macpaul Lin.
149096963cSMacpaul Lin  */
159096963cSMacpaul Lin 
169096963cSMacpaul Lin #include <common.h>
179096963cSMacpaul Lin #include <watchdog.h>
189096963cSMacpaul Lin #include <asm/io.h>
1904c2dd82SMacpaul Lin #include <faraday/ftwdt010_wdt.h>
209096963cSMacpaul Lin 
219096963cSMacpaul Lin /*
229096963cSMacpaul Lin  * Set the watchdog time interval.
239096963cSMacpaul Lin  * Counter is 32 bit.
249096963cSMacpaul Lin  */
ftwdt010_wdt_settimeout(unsigned int timeout)2504c2dd82SMacpaul Lin int ftwdt010_wdt_settimeout(unsigned int timeout)
269096963cSMacpaul Lin {
279096963cSMacpaul Lin 	unsigned int reg;
289096963cSMacpaul Lin 
299096963cSMacpaul Lin 	struct ftwdt010_wdt *wd = (struct ftwdt010_wdt *)CONFIG_FTWDT010_BASE;
309096963cSMacpaul Lin 
319096963cSMacpaul Lin 	debug("Activating WDT..\n");
329096963cSMacpaul Lin 
339096963cSMacpaul Lin 	/* Check if disabled */
349096963cSMacpaul Lin 	if (readl(&wd->wdcr) & ~FTWDT010_WDCR_ENABLE) {
359096963cSMacpaul Lin 		printf("sorry, watchdog is disabled\n");
369096963cSMacpaul Lin 		return -1;
379096963cSMacpaul Lin 	}
389096963cSMacpaul Lin 
399096963cSMacpaul Lin 	/*
409096963cSMacpaul Lin 	 * In a 66MHz system,
419096963cSMacpaul Lin 	 * if you set WDLOAD as 0x03EF1480 (66000000)
429096963cSMacpaul Lin 	 * the reset timer is 1 second.
439096963cSMacpaul Lin 	 */
449096963cSMacpaul Lin 	reg = FTWDT010_WDLOAD(timeout * FTWDT010_TIMEOUT_FACTOR);
459096963cSMacpaul Lin 
469096963cSMacpaul Lin 	writel(reg, &wd->wdload);
479096963cSMacpaul Lin 
489096963cSMacpaul Lin 	return 0;
499096963cSMacpaul Lin }
509096963cSMacpaul Lin 
ftwdt010_wdt_reset(void)5104c2dd82SMacpaul Lin void ftwdt010_wdt_reset(void)
529096963cSMacpaul Lin {
539096963cSMacpaul Lin 	struct ftwdt010_wdt *wd = (struct ftwdt010_wdt *)CONFIG_FTWDT010_BASE;
549096963cSMacpaul Lin 
559096963cSMacpaul Lin 	/* clear control register */
569096963cSMacpaul Lin 	writel(0, &wd->wdcr);
579096963cSMacpaul Lin 
589096963cSMacpaul Lin 	/* Write Magic number */
599096963cSMacpaul Lin 	writel(FTWDT010_WDRESTART_MAGIC, &wd->wdrestart);
609096963cSMacpaul Lin 
619096963cSMacpaul Lin 	/* Enable WDT */
629096963cSMacpaul Lin 	writel((FTWDT010_WDCR_RST | FTWDT010_WDCR_ENABLE), &wd->wdcr);
639096963cSMacpaul Lin }
649096963cSMacpaul Lin 
ftwdt010_wdt_disable(void)6504c2dd82SMacpaul Lin void ftwdt010_wdt_disable(void)
669096963cSMacpaul Lin {
679096963cSMacpaul Lin 	struct ftwdt010_wdt *wd = (struct ftwdt010_wdt *)CONFIG_FTWDT010_BASE;
689096963cSMacpaul Lin 
699096963cSMacpaul Lin 	debug("Deactivating WDT..\n");
709096963cSMacpaul Lin 
719096963cSMacpaul Lin 	/*
729096963cSMacpaul Lin 	 * It was defined with CONFIG_WATCHDOG_NOWAYOUT in Linux
739096963cSMacpaul Lin 	 *
749096963cSMacpaul Lin 	 * Shut off the timer.
759096963cSMacpaul Lin 	 * Lock it in if it's a module and we defined ...NOWAYOUT
769096963cSMacpaul Lin 	 */
779096963cSMacpaul Lin 	writel(0, &wd->wdcr);
789096963cSMacpaul Lin }
799096963cSMacpaul Lin 
8004c2dd82SMacpaul Lin #if defined(CONFIG_HW_WATCHDOG)
hw_watchdog_reset(void)8104c2dd82SMacpaul Lin void hw_watchdog_reset(void)
829096963cSMacpaul Lin {
839096963cSMacpaul Lin 	ftwdt010_wdt_reset();
849096963cSMacpaul Lin }
859096963cSMacpaul Lin 
hw_watchdog_init(void)869096963cSMacpaul Lin void hw_watchdog_init(void)
879096963cSMacpaul Lin {
889096963cSMacpaul Lin 	/* set timer in ms */
899096963cSMacpaul Lin 	ftwdt010_wdt_settimeout(CONFIG_FTWDT010_HW_TIMEOUT * 1000);
909096963cSMacpaul Lin }
9104c2dd82SMacpaul Lin #endif
92