static void sh_wdt_start(struct sh_wdt *wdt) { unsigned long flags; u8 csr; spin_lock_irqsave(&shwdt_lock, flags); next_heartbeat = jiffies + (heartbeat * HZ); mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); csr = sh_wdt_read_csr(); csr |= WTCSR_WT | clock_division_ratio; sh_wdt_write_csr(csr); sh_wdt_write_cnt(0); csr = sh_wdt_read_csr(); csr |= WTCSR_TME; csr &= ~WTCSR_RSTS; sh_wdt_write_csr(csr); #ifdef CONFIG_CPU_SH2 csr = sh_wdt_read_rstcsr(); csr &= ~RSTCSR_RSTS; sh_wdt_write_rstcsr(csr); #endif spin_unlock_irqrestore(&shwdt_lock, flags); }
/** * sh_wdt_ping - Ping the Watchdog * * @data: Unused * * Clears overflow bit, resets timer counter. */ static void sh_wdt_ping(unsigned long data) { if (time_before(jiffies, next_heartbeat)) { sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF)); sh_wdt_write_cnt(0); timer.expires = next_ping_period(clock_division_ratio); add_timer(&timer); } }
/** * sh_wdt_start - Start the Watchdog * * Starts the watchdog. */ static void sh_wdt_start(void) { timer.expires = next_ping_period(clock_division_ratio); next_heartbeat = jiffies + (sh_heartbeat * HZ); add_timer(&timer); sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096); sh_wdt_write_cnt(0); sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME)); }
/** * sh_wdt_ping - Ping the Watchdog * * @data: Unused * * Clears overflow bit, resets timer counter. */ static void sh_wdt_ping(unsigned long data) { if (time_before(jiffies, next_heartbeat)) { __u8 csr; csr = sh_wdt_read_csr(); csr &= ~WTCSR_IOVF; sh_wdt_write_csr(csr); sh_wdt_write_cnt(0); mod_timer(&timer, next_ping_period(clock_division_ratio)); } else { printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); } }
static int sh_wdt_start(struct watchdog_device *wdt_dev) { struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev); unsigned long flags; u8 csr; pm_runtime_get_sync(wdt->dev); clk_enable(wdt->clk); spin_lock_irqsave(&wdt->lock, flags); next_heartbeat = jiffies + (heartbeat * HZ); mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); csr = sh_wdt_read_csr(); csr |= WTCSR_WT | clock_division_ratio; sh_wdt_write_csr(csr); sh_wdt_write_cnt(0); /* * These processors have a bit of an inconsistent initialization * process.. starting with SH-3, RSTS was moved to WTCSR, and the * RSTCSR register was removed. * * On the SH-2 however, in addition with bits being in different * locations, we must deal with RSTCSR outright.. */ csr = sh_wdt_read_csr(); csr |= WTCSR_TME; csr &= ~WTCSR_RSTS; sh_wdt_write_csr(csr); #ifdef CONFIG_CPU_SH2 csr = sh_wdt_read_rstcsr(); csr &= ~RSTCSR_RSTS; sh_wdt_write_rstcsr(csr); #endif spin_unlock_irqrestore(&wdt->lock, flags); return 0; }
/** * sh_wdt_start - Start the Watchdog * * Starts the watchdog. */ static void sh_wdt_start(void) { __u8 csr; next_heartbeat = jiffies + (heartbeat * HZ); mod_timer(&timer, next_ping_period(clock_division_ratio)); csr = sh_wdt_read_csr(); csr |= WTCSR_WT | clock_division_ratio; sh_wdt_write_csr(csr); sh_wdt_write_cnt(0); /* * These processors have a bit of an inconsistent initialization * process.. starting with SH-3, RSTS was moved to WTCSR, and the * RSTCSR register was removed. * * On the SH-2 however, in addition with bits being in different * locations, we must deal with RSTCSR outright.. */ csr = sh_wdt_read_csr(); csr |= WTCSR_TME; csr &= ~WTCSR_RSTS; sh_wdt_write_csr(csr); #ifdef CONFIG_CPU_SH2 /* * Whoever came up with the RSTCSR semantics must've been smoking * some of the good stuff, since in addition to the WTCSR/WTCNT write * brain-damage, it's managed to f**k things up one step further.. * * If we need to clear the WOVF bit, the upper byte has to be 0xa5.. * but if we want to touch RSTE or RSTS, the upper byte has to be * 0x5a.. */ csr = sh_wdt_read_rstcsr(); csr &= ~RSTCSR_RSTS; sh_wdt_write_rstcsr(csr); #endif }
static void sh_wdt_ping(unsigned long data) { struct sh_wdt *wdt = (struct sh_wdt *)data; unsigned long flags; spin_lock_irqsave(&wdt->lock, flags); if (time_before(jiffies, next_heartbeat)) { u8 csr; csr = sh_wdt_read_csr(); csr &= ~WTCSR_IOVF; sh_wdt_write_csr(csr); sh_wdt_write_cnt(0); mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); } else dev_warn(wdt->dev, "Heartbeat lost! Will not ping " "the watchdog\n"); spin_unlock_irqrestore(&wdt->lock, flags); }
static int __devinit sh_wdt_probe(struct platform_device *pdev) { struct sh_wdt *wdt; struct resource *res; int rc; /* * As this driver only covers the global watchdog case, reject * any attempts to register per-CPU watchdogs. */ if (pdev->id != -1) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (unlikely(!res)) return -EINVAL; wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); if (unlikely(!wdt)) return -ENOMEM; wdt->dev = &pdev->dev; wdt->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(wdt->clk)) { /* * Clock framework support is optional, continue on * anyways if we don't find a matching clock. */ wdt->clk = NULL; } wdt->base = devm_request_and_ioremap(wdt->dev, res); if (unlikely(!wdt->base)) { rc = -EADDRNOTAVAIL; goto err; } watchdog_set_nowayout(&sh_wdt_dev, nowayout); watchdog_set_drvdata(&sh_wdt_dev, wdt); spin_lock_init(&wdt->lock); rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat); if (unlikely(rc)) { /* Default timeout if invalid */ sh_wdt_set_heartbeat(&sh_wdt_dev, WATCHDOG_HEARTBEAT); dev_warn(&pdev->dev, "heartbeat value must be 1<=x<=3600, using %d\n", sh_wdt_dev.timeout); } dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n", sh_wdt_dev.timeout, nowayout); rc = watchdog_register_device(&sh_wdt_dev); if (unlikely(rc)) { dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc); goto err; } init_timer(&wdt->timer); wdt->timer.function = sh_wdt_ping; wdt->timer.data = (unsigned long)wdt; wdt->timer.expires = next_ping_period(clock_division_ratio); platform_set_drvdata(pdev, wdt); dev_info(&pdev->dev, "initialized.\n"); pm_runtime_enable(&pdev->dev); return 0; err: clk_put(wdt->clk); return rc; }