/*
 * Blackfin nmi_watchdog Driver
 *
 * Originally based on bfin_wdt.c
 * Copyright 2010-2010 Analog Devices Inc.
 *		Graff Yang <graf.yang@analog.com>
 *
 * Enter bugs at http://blackfin.uclinux.org/
 *
 * Licensed under the GPL-2 or later.
 */

#include <linux/bitops.h>
#include <linux/hardirq.h>
#include <linux/syscore_ops.h>
#include <linux/pm.h>
#include <linux/nmi.h>
#include <linux/smp.h>
#include <linux/timer.h>
#include <linux/sched/debug.h>
#include <asm/blackfin.h>
#include <linux/atomic.h>
#include <asm/cacheflush.h>
#include <asm/bfin_watchdog.h>

#define DRV_NAME "nmi-wdt"

#define NMI_WDT_TIMEOUT 5          /* 5 seconds */
#define NMI_CHECK_TIMEOUT (4 * HZ) /* 4 seconds in jiffies */
static int nmi_wdt_cpu = 1;

static unsigned int timeout = NMI_WDT_TIMEOUT;
static int nmi_active;

static unsigned short wdoga_ctl;
static unsigned int wdoga_cnt;
static struct corelock_slot saved_corelock;
static atomic_t nmi_touched[NR_CPUS];
static struct timer_list ntimer;

enum {
	COREA_ENTER_NMI = 0,
	COREA_EXIT_NMI,
	COREB_EXIT_NMI,

	NMI_EVENT_NR,
};
static unsigned long nmi_event __attribute__ ((__section__(".l2.bss")));

/* we are in nmi, non-atomic bit ops is safe */
static inline void set_nmi_event(int event)
{
	__set_bit(event, &nmi_event);
}

static inline void wait_nmi_event(int event)
{
	while (!test_bit(event, &nmi_event))
		barrier();
	__clear_bit(event, &nmi_event);
}

static inline void send_corea_nmi(void)
{
	wdoga_ctl = bfin_read_WDOGA_CTL();
	wdoga_cnt = bfin_read_WDOGA_CNT();

	bfin_write_WDOGA_CTL(WDEN_DISABLE);
	bfin_write_WDOGA_CNT(0);
	bfin_write_WDOGA_CTL(WDEN_ENABLE | ICTL_NMI);
}

static inline void restore_corea_nmi(void)
{
	bfin_write_WDOGA_CTL(WDEN_DISABLE);
	bfin_write_WDOGA_CTL(WDOG_EXPIRED | WDEN_DISABLE | ICTL_NONE);

	bfin_write_WDOGA_CNT(wdoga_cnt);
	bfin_write_WDOGA_CTL(wdoga_ctl);
}

static inline void save_corelock(void)
{
	saved_corelock = corelock;
	corelock.lock = 0;
}

static inline void restore_corelock(void)
{
	corelock = saved_corelock;
}


static inline void nmi_wdt_keepalive(void)
{
	bfin_write_WDOGB_STAT(0);
}

static inline void nmi_wdt_stop(void)
{
	bfin_write_WDOGB_CTL(WDEN_DISABLE);
}

/* before calling this function, you must stop the WDT */
static inline void nmi_wdt_clear(void)
{
	/* clear TRO bit, disable event generation */
	bfin_write_WDOGB_CTL(WDOG_EXPIRED | WDEN_DISABLE | ICTL_NONE);
}

static inline void nmi_wdt_start(void)
{
	bfin_write_WDOGB_CTL(WDEN_ENABLE | ICTL_NMI);
}

static inline int nmi_wdt_running(void)
{
	return ((bfin_read_WDOGB_CTL() & WDEN_MASK) != WDEN_DISABLE);
}

static inline int nmi_wdt_set_timeout(unsigned long t)
{
	u32 cnt, max_t, sclk;
	int run;

	sclk = get_sclk();
	max_t = -1 / sclk;
	cnt = t * sclk;
	if (t > max_t) {
		pr_warning("NMI: timeout value is too large\n");
		return -EINVAL;
	}

	run = nmi_wdt_running();
	nmi_wdt_stop();
	bfin_write_WDOGB_CNT(cnt);
	if (run)
		nmi_wdt_start();

	timeout = t;

	return 0;
}

int check_nmi_wdt_touched(void)
{
	unsigned int this_cpu = smp_processor_id();
	unsigned int cpu;
	cpumask_t mask;

	cpumask_copy(&mask, cpu_online_mask);
	if (!atomic_read(&nmi_touched[this_cpu]))
		return 0;

	atomic_set(&nmi_touched[this_cpu], 0);

	cpumask_clear_cpu(this_cpu, &mask);
	for_each_cpu(cpu, &mask) {
		invalidate_dcache_range((unsigned long)(&nmi_touched[cpu]),
				(unsigned long)(&nmi_touched[cpu]));
		if (!atomic_read(&nmi_touched[cpu]))
			return 0;
		atomic_set(&nmi_touched[cpu], 0);
	}

	return 1;
}

static void nmi_wdt_timer(unsigned long data)
{
	if (check_nmi_wdt_touched())
		nmi_wdt_keepalive();

	mod_timer(&ntimer, jiffies + NMI_CHECK_TIMEOUT);
}

static int __init init_nmi_wdt(void)
{
	nmi_wdt_set_timeout(timeout);
	nmi_wdt_start();
	nmi_active = true;

	init_timer(&ntimer);
	ntimer.function = nmi_wdt_timer;
	ntimer.expires = jiffies + NMI_CHECK_TIMEOUT;
	add_timer(&ntimer);

	pr_info("nmi_wdt: initialized: timeout=%d sec\n", timeout);
	return 0;
}
device_initcall(init_nmi_wdt);

void arch_touch_nmi_watchdog(void)
{
	atomic_set(&nmi_touched[smp_processor_id()], 1);
}

/* Suspend/resume support */
#ifdef CONFIG_PM
static int nmi_wdt_suspend(void)
{
	nmi_wdt_stop();
	return 0;
}

static void nmi_wdt_resume(void)
{
	if (nmi_active)
		nmi_wdt_start();
}

static struct syscore_ops nmi_syscore_ops = {
	.resume		= nmi_wdt_resume,
	.suspend	= nmi_wdt_suspend,
};

static int __init init_nmi_wdt_syscore(void)
{
	if (nmi_active)
		register_syscore_ops(&nmi_syscore_ops);

	return 0;
}
late_initcall(init_nmi_wdt_syscore);

#endif	/* CONFIG_PM */


asmlinkage notrace void do_nmi(struct pt_regs *fp)
{
	unsigned int cpu = smp_processor_id();
	nmi_enter();

	cpu_pda[cpu].__nmi_count += 1;

	if (cpu == nmi_wdt_cpu) {
		/* CoreB goes here first */

		/* reload the WDOG_STAT */
		nmi_wdt_keepalive();

		/* clear nmi interrupt for CoreB */
		nmi_wdt_stop();
		nmi_wdt_clear();

		/* trigger NMI interrupt of CoreA */
		send_corea_nmi();

		/* waiting CoreB to enter NMI */
		wait_nmi_event(COREA_ENTER_NMI);

		/* recover WDOGA's settings */
		restore_corea_nmi();

		save_corelock();

		/* corelock is save/cleared, CoreA is dummping messages */

		wait_nmi_event(COREA_EXIT_NMI);
	} else {
		/* OK, CoreA entered NMI */
		set_nmi_event(COREA_ENTER_NMI);
	}

	pr_emerg("\nNMI Watchdog detected LOCKUP, dump for CPU %d\n", cpu);
	dump_bfin_process(fp);
	dump_bfin_mem(fp);
	show_regs(fp);
	dump_bfin_trace_buffer();
	show_stack(current, (unsigned long *)fp);

	if (cpu == nmi_wdt_cpu) {
		pr_emerg("This fault is not recoverable, sorry!\n");

		/* CoreA dump finished, restore the corelock */
		restore_corelock();

		set_nmi_event(COREB_EXIT_NMI);
	} else {
		/* CoreB dump finished, notice the CoreA we are done */
		set_nmi_event(COREA_EXIT_NMI);

		/* synchronize with CoreA */
		wait_nmi_event(COREB_EXIT_NMI);
	}

	nmi_exit();
}
