Source
x
// SPDX-License-Identifier: GPL-2.0+
/*
* Broadcom BCM63xx SoC watchdog driver
*
* Copyright (C) 2007, Miguel Gaio <miguel.gaio@efixo.com>
* Copyright (C) 2008, Florian Fainelli <florian@openwrt.org>
*
*/
/* Fclk */
/* seconds */
/* seconds */
static struct {
void __iomem *regs;
struct timer_list timer;
unsigned long inuse;
atomic_t ticks;
} bcm63xx_wdt_device;
static int expect_close;
static int wdt_time = WDT_DEFAULT_TIME;
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
/* HW functions */
static void bcm63xx_wdt_hw_start(void)
{
bcm_writel(0xfffffffe, bcm63xx_wdt_device.regs + WDT_DEFVAL_REG);
bcm_writel(WDT_START_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
bcm_writel(WDT_START_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
}
static void bcm63xx_wdt_hw_stop(void)
{
bcm_writel(WDT_STOP_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
bcm_writel(WDT_STOP_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
}
static void bcm63xx_wdt_isr(void *data)
{
struct pt_regs *regs = get_irq_regs();
die(PFX " fire", regs);
}
static void bcm63xx_timer_tick(struct timer_list *unused)
{
if (!atomic_dec_and_test(&bcm63xx_wdt_device.ticks)) {
bcm63xx_wdt_hw_start();
mod_timer(&bcm63xx_wdt_device.timer, jiffies + HZ);
} else
pr_crit("watchdog will restart system\n");
}
static void bcm63xx_wdt_pet(void)
{
atomic_set(&bcm63xx_wdt_device.ticks, wdt_time);
}
static void bcm63xx_wdt_start(void)
{