diff options
author | Arnd Bergmann <arnd@arndb.de> | 2018-03-07 22:23:24 +0100 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2018-03-16 10:55:47 +0100 |
commit | 4ba66a9760722ccbb691b8f7116cad2f791cca7b (patch) | |
tree | e29f9624ad0b13aa11860e39440bbc5e24d18a30 /arch/blackfin/kernel/nmi.c | |
parent | arch: remove score port (diff) | |
download | linux-4ba66a9760722ccbb691b8f7116cad2f791cca7b.tar.xz linux-4ba66a9760722ccbb691b8f7116cad2f791cca7b.zip |
arch: remove blackfin port
The Analog Devices Blackfin port was added in 2007 and was rather
active for a while, but all work on it has come to a standstill
over time, as Analog have changed their product line-up.
Aaron Wu confirmed that the architecture port is no longer relevant,
and multiple people suggested removing blackfin independently because
of some of its oddities like a non-working SMP port, and the amount of
duplication between the chip variants, which cause extra work when
doing cross-architecture changes.
Link: https://docs.blackfin.uclinux.org/
Acked-by: Aaron Wu <Aaron.Wu@analog.com>
Acked-by: Bryan Wu <cooloney@gmail.com>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Mike Frysinger <vapier@chromium.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/blackfin/kernel/nmi.c')
-rw-r--r-- | arch/blackfin/kernel/nmi.c | 287 |
1 files changed, 0 insertions, 287 deletions
diff --git a/arch/blackfin/kernel/nmi.c b/arch/blackfin/kernel/nmi.c deleted file mode 100644 index 8a211d95821f..000000000000 --- a/arch/blackfin/kernel/nmi.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * 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(struct timer_list *unused) -{ - 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; - - timer_setup(&ntimer, nmi_wdt_timer, 0); - 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(); -} |