static long sci_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int ret = -ENOTTY;
	int time, period;
	void __user *argp = (void __user *) arg;
	int __user *p = argp;

	switch (cmd)
	{
	case WDIOC_GETSUPPORT:
		ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
		break;

	case WDIOC_GETSTATUS:
		ret = put_user(0, p);
		break;

	case WDIOC_GETBOOTSTATUS:
		ret = put_user(boot_status, p);
		break;

	case WDIOC_GETPRETIMEOUT:
		ret = put_user(feed_period, p);
		break;

	case WDIOC_SETPRETIMEOUT:
		ret = get_user(period, p);
		if (ret)
			break;

		WDG_LOAD_TIMER_VALUE(period * WDT_FREQ);
		feed_period = period;
		break;

	case WDIOC_KEEPALIVE:
		WDG_LOAD_TIMER_VALUE(margin * WDT_FREQ);
		ret = 0;
		break;

	case WDIOC_SETTIMEOUT:
		ret = get_user(time, p);
		if (ret)
			break;

		if (time <= 0 || (WDT_FREQ * (long long) time >= 0xffffffff)) {
			ret = -EINVAL;
			break;
		}

		WDG_LOAD_TIMER_VALUE(time * WDT_FREQ);
		margin = time;

		/*fall through*/
	case WDIOC_GETTIMEOUT:
		ret = put_user(margin, p);
		break;
	}
	return ret;
}
/*
 * This is a hw watchdog starts after init, and fed by a timer started
 * by the watchdog driver itself. It can also be fed from userland.
 * The watchdog will be stopped in system suspend, and restarted in
 * system resume.
 */
static void watchdog_feeder(unsigned long data)
{
	DEBUG_PRINT(WDT "%s, margin=%d, feed_period=%d\n", __FUNCTION__, margin,
			feed_period);
	WDG_LOAD_TIMER_VALUE(margin * WDT_FREQ);
	mod_timer(&feeder_timer, jiffies + (feed_period * HZ));
}
Beispiel #3
0
/* use ana watchdog to wake up */
void pm_debug_set_apwdt(void)
{
	uint32_t cnt = 0;
	uint32_t ms = 5000;
	cnt = (ms * WDG_CLK) / 1000;

	sci_glb_set(INT_IRQ_ENB, BIT(11));
	/*enable interface clk*/
	sci_adi_set(ANA_AGEN, AGEN_WDG_EN);
	/*enable work clk*/
	sci_adi_set(ANA_RTC_CLK_EN, AGEN_RTC_WDG_EN);
	sci_adi_raw_write(WDG_LOCK, WDG_UNLOCK_KEY);
	sci_adi_set(WDG_CTRL, WDG_NEW_VER_EN);
	WDG_LOAD_TIMER_VALUE(0x80000);
	WDG_LOAD_TIMER_INT_VALUE(0x40000);
	sci_adi_set(WDG_CTRL, WDG_CNT_EN_BIT | WDG_INT_EN_BIT| WDG_RST_EN_BIT);
	sci_adi_raw_write(WDG_LOCK, (uint16_t) (~WDG_UNLOCK_KEY));
	sci_adi_set(ANA_REG_INT_EN, BIT(3));
#if 0
	do{
		udelay(1000);
		printk("INTC1 mask:0x%08x raw:0x%08x en:0x%08x\n", __raw_readl(INTCV1_IRQ_MSKSTS),__raw_readl(INTCV1_IRQ_RAW), __raw_readl(INTCV1_IRQ_EN));
		printk("INT mask:0x%08x raw:0x%08x en:0x%08x ana 0x%08x\n", __raw_readl(INT_IRQ_STS),__raw_readl(INT_IRQ_RAW), __raw_readl(INT_IRQ_ENB), sci_adi_read(ANA_REG_INT_MASK_STATUS));
		printk("ANA mask:0x%08x raw:0x%08x en:0x%08x\n", sci_adi_read(ANA_REG_INT_MASK_STATUS), sci_adi_read(ANA_REG_INT_RAW_STATUS), sci_adi_read(ANA_REG_INT_EN));
		printk("wdg cnt low 0x%08x high 0x%08x\n", sci_adi_read(WDG_CNT_LOW), sci_adi_read(WDG_CNT_HIGH));
	}while(0);
#endif
}
static ssize_t sci_write(struct file *file, const char __user *data, size_t len,
		loff_t *ppos)
{
	/* TODO: we should have a new reboot reason */
	/*
	   sci_adi_raw_write(ANA_RST_STATUS, HWRST_STATUS_NORMAL);
	   */
	if (len)
		WDG_LOAD_TIMER_VALUE(margin * WDT_FREQ);

	return len;
}
static int sci_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(1, &wdt_users))
		return -EBUSY;

	/* started the watchdog when it's openned for the 1st time */
	if (wdt_state == 0) {
		/* start the watchdog */
		sci_adi_set(ANA_AGEN, AGEN_WDG_EN | AGEN_RTC_ARCH_EN | AGEN_RTC_WDG_EN);
		sci_adi_raw_write (WDG_LOCK, WDG_UNLOCK_KEY);
		sci_adi_clr (WDG_CTRL, WDG_INT_EN_BIT);
		WDG_LOAD_TIMER_VALUE(margin * WDT_FREQ);
#ifdef CONFIG_ARCH_SC8825
		sci_adi_set(WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT);
#else
		sci_adi_set(WDG_CTRL, WDG_CNT_EN_BIT);
#endif
		mod_timer(&feeder_timer, jiffies + (feed_period * HZ));
		wdt_state = 1;
	}

	return nonseekable_open(inode, file);
}