void samsung_wdt_reset(void) { if (!wdt_base) { pr_err("%s: wdt reset not initialized\n", __func__); /* delay to allow the serial port to show the message */ mdelay(50); return; } if (!IS_ERR(wdt_clock)) clk_prepare_enable(wdt_clock); /* disable watchdog, to be safe */ __raw_writel(0, wdt_base + S3C2410_WTCON); /* put initial values into count and data */ __raw_writel(0x80, wdt_base + S3C2410_WTCNT); __raw_writel(0x80, wdt_base + S3C2410_WTDAT); /* set the watchdog to go and reset... */ __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV16 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x20), wdt_base + S3C2410_WTCON); /* wait for reset to assert... */ mdelay(500); pr_err("Watchdog reset failed to assert reset\n"); /* delay to allow the serial port to show the message */ mdelay(50); }
static void watchdog_start(void) { unsigned int val; unsigned long flags; spin_lock_irqsave(&wdt_lock, flags); /* set to PCLK / 256 / 128 */ val = S3C2410_WTCON_DIV128; val |= S3C2410_WTCON_PRESCALE(255); writel(val, S3C2410_WTCON); /* program initial count */ writel(watchdog_reset * TPS, S3C2410_WTCNT); writel(watchdog_reset * TPS, S3C2410_WTDAT); /* start timer */ val |= S3C2410_WTCON_RSTEN | S3C2410_WTCON_ENABLE; writel(val, S3C2410_WTCON); spin_unlock_irqrestore(&wdt_lock, flags); /* make sure we're ready to pet the dog */ #if defined(PET_BY_WORKQUEUE) queue_delayed_work_on(0, watchdog_wq, &watchdog_work, watchdog_pet * HZ); #elif defined(PET_BY_DIRECT_TIMER) pet_watchdog_timer.expires = jiffies + watchdog_pet * HZ; add_timer_on(&pet_watchdog_timer, 0); #else hrtimer_start(&watchdog_timer, ktime_set(watchdog_pet, 0), HRTIMER_MODE_REL); #endif }
static int s3c2410wdt_set_heartbeat(int timeout) { unsigned int freq = clk_get_rate(wdt_clock); unsigned int count; unsigned int divisor = 1; unsigned long wtcon; if (timeout < 1) return -EINVAL; /* I think someone must have missed a divide-by-2 in the 2410, * as a divisor of 128 gives half the calculated delay... */ freq /= 128/2; count = timeout * freq; DBG("%s: count=%d, timeout=%d, freq=%d\n", __FUNCTION__, count, timeout, freq); /* if the count is bigger than the watchdog register, then work out what we need to do (and if) we can actually make this value */ if (count >= 0x10000) { for (divisor = 1; divisor <= 0x100; divisor++) { if ((count / divisor) < 0x10000) break; } if ((count / divisor) >= 0x10000) { printk(KERN_ERR PFX "timeout %d too big\n", timeout); return -EINVAL; } } tmr_margin = timeout; DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n", __FUNCTION__, timeout, divisor, count, count/divisor); count /= divisor; wdt_count = count; /* update the pre-scaler */ wtcon = readl(wdt_base + S3C2410_WTCON); wtcon &= ~S3C2410_WTCON_PRESCALE_MASK; wtcon |= S3C2410_WTCON_PRESCALE(divisor-1); writel(count, wdt_base + S3C2410_WTDAT); writel(wtcon, wdt_base + S3C2410_WTCON); return 0; }
static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeout) { unsigned long freq = clk_get_rate(rate_wdt_clock); unsigned int count; unsigned int divisor = 1; unsigned long wtcon; if (timeout < 1) return -EINVAL; freq /= 128; count = timeout * freq; DBG("%s: count=%d, timeout=%d, freq=%lu\n", __func__, count, timeout, freq); /* if the count is bigger than the watchdog register, then work out what we need to do (and if) we can actually make this value */ if (count >= 0x10000) { for (divisor = 1; divisor <= 0x100; divisor++) { if ((count / divisor) < 0x10000) break; } if ((count / divisor) >= 0x10000) { dev_err(wdt_dev, "timeout %d too big\n", timeout); return -EINVAL; } } DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n", __func__, timeout, divisor, count, count/divisor); count /= divisor; wdt_count = count; /* update the pre-scaler */ wtcon = readl(wdt_base + S3C2410_WTCON); wtcon &= ~S3C2410_WTCON_PRESCALE_MASK; wtcon |= S3C2410_WTCON_PRESCALE(divisor-1); writel(count, wdt_base + S3C2410_WTDAT); writel(wtcon, wdt_base + S3C2410_WTCON); wdd->timeout = (count * divisor) / freq; return 0; }
static void watchdog_start(void) { unsigned int val; /* set to PCLK / 256 / 128 */ val = S3C2410_WTCON_DIV128; val |= S3C2410_WTCON_PRESCALE(255); writel(val, S3C2410_WTCON); /* program initial count */ writel(watchdog_reset, S3C2410_WTCNT); writel(watchdog_reset, S3C2410_WTDAT); /* start timer */ val |= S3C2410_WTCON_RSTEN | S3C2410_WTCON_ENABLE; writel(val, S3C2410_WTCON); /* make sure we're ready to pet the dog */ queue_delayed_work(watchdog_wq, &watchdog_work, watchdog_pet); }