78 lines
		
	
	
	
		
			1.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			78 lines
		
	
	
	
		
			1.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright (C) 2007 Atmel Corporation
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is free software; you can redistribute it and/or modify
							 | 
						||
| 
								 | 
							
								 * it under the terms of the GNU General Public License version 2 as
							 | 
						||
| 
								 | 
							
								 * published by the Free Software Foundation.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#include <linux/delay.h>
							 | 
						||
| 
								 | 
							
								#include <linux/kdebug.h>
							 | 
						||
| 
								 | 
							
								#include <linux/notifier.h>
							 | 
						||
| 
								 | 
							
								#include <linux/sched.h>
							 | 
						||
| 
								 | 
							
								#include <linux/hardirq.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								enum nmi_action {
							 | 
						||
| 
								 | 
							
									NMI_SHOW_STATE	= 1 << 0,
							 | 
						||
| 
								 | 
							
									NMI_SHOW_REGS	= 1 << 1,
							 | 
						||
| 
								 | 
							
									NMI_DIE		= 1 << 2,
							 | 
						||
| 
								 | 
							
									NMI_DEBOUNCE	= 1 << 3,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static unsigned long nmi_actions;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int nmi_debug_notify(struct notifier_block *self,
							 | 
						||
| 
								 | 
							
										unsigned long val, void *data)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									struct die_args *args = data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (likely(val != DIE_NMI))
							 | 
						||
| 
								 | 
							
										return NOTIFY_DONE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (nmi_actions & NMI_SHOW_STATE)
							 | 
						||
| 
								 | 
							
										show_state();
							 | 
						||
| 
								 | 
							
									if (nmi_actions & NMI_SHOW_REGS)
							 | 
						||
| 
								 | 
							
										show_regs(args->regs);
							 | 
						||
| 
								 | 
							
									if (nmi_actions & NMI_DEBOUNCE)
							 | 
						||
| 
								 | 
							
										mdelay(10);
							 | 
						||
| 
								 | 
							
									if (nmi_actions & NMI_DIE)
							 | 
						||
| 
								 | 
							
										return NOTIFY_BAD;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return NOTIFY_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static struct notifier_block nmi_debug_nb = {
							 | 
						||
| 
								 | 
							
									.notifier_call = nmi_debug_notify,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int __init nmi_debug_setup(char *str)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									char *p, *sep;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									register_die_notifier(&nmi_debug_nb);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (*str != '=')
							 | 
						||
| 
								 | 
							
										return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (p = str + 1; *p; p = sep + 1) {
							 | 
						||
| 
								 | 
							
										sep = strchr(p, ',');
							 | 
						||
| 
								 | 
							
										if (sep)
							 | 
						||
| 
								 | 
							
											*sep = 0;
							 | 
						||
| 
								 | 
							
										if (strcmp(p, "state") == 0)
							 | 
						||
| 
								 | 
							
											nmi_actions |= NMI_SHOW_STATE;
							 | 
						||
| 
								 | 
							
										else if (strcmp(p, "regs") == 0)
							 | 
						||
| 
								 | 
							
											nmi_actions |= NMI_SHOW_REGS;
							 | 
						||
| 
								 | 
							
										else if (strcmp(p, "debounce") == 0)
							 | 
						||
| 
								 | 
							
											nmi_actions |= NMI_DEBOUNCE;
							 | 
						||
| 
								 | 
							
										else if (strcmp(p, "die") == 0)
							 | 
						||
| 
								 | 
							
											nmi_actions |= NMI_DIE;
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											printk(KERN_WARNING "NMI: Unrecognized action `%s'\n",
							 | 
						||
| 
								 | 
							
												p);
							 | 
						||
| 
								 | 
							
										if (!sep)
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								__setup("nmi_debug", nmi_debug_setup);
							 |