xref: /openbmc/linux/arch/sh/boards/mach-sdk7786/nmi.c (revision 76496f8f)
176496f8fSPaul Mundt /*
276496f8fSPaul Mundt  * SDK7786 FPGA NMI Support.
376496f8fSPaul Mundt  *
476496f8fSPaul Mundt  * Copyright (C) 2010  Paul Mundt
576496f8fSPaul Mundt  *
676496f8fSPaul Mundt  * This file is subject to the terms and conditions of the GNU General Public
776496f8fSPaul Mundt  * License.  See the file "COPYING" in the main directory of this archive
876496f8fSPaul Mundt  * for more details.
976496f8fSPaul Mundt  */
1076496f8fSPaul Mundt #include <linux/init.h>
1176496f8fSPaul Mundt #include <linux/kernel.h>
1276496f8fSPaul Mundt #include <linux/string.h>
1376496f8fSPaul Mundt #include <mach/fpga.h>
1476496f8fSPaul Mundt 
1576496f8fSPaul Mundt enum {
1676496f8fSPaul Mundt 	NMI_MODE_MANUAL,
1776496f8fSPaul Mundt 	NMI_MODE_AUX,
1876496f8fSPaul Mundt 	NMI_MODE_MASKED,
1976496f8fSPaul Mundt 	NMI_MODE_ANY,
2076496f8fSPaul Mundt 	NMI_MODE_UNKNOWN,
2176496f8fSPaul Mundt };
2276496f8fSPaul Mundt 
2376496f8fSPaul Mundt /*
2476496f8fSPaul Mundt  * Default to the manual NMI switch.
2576496f8fSPaul Mundt  */
2676496f8fSPaul Mundt static unsigned int __initdata nmi_mode = NMI_MODE_ANY;
2776496f8fSPaul Mundt 
2876496f8fSPaul Mundt static int __init nmi_mode_setup(char *str)
2976496f8fSPaul Mundt {
3076496f8fSPaul Mundt 	if (!str)
3176496f8fSPaul Mundt 		return 0;
3276496f8fSPaul Mundt 
3376496f8fSPaul Mundt 	if (strcmp(str, "manual") == 0)
3476496f8fSPaul Mundt 		nmi_mode = NMI_MODE_MANUAL;
3576496f8fSPaul Mundt 	else if (strcmp(str, "aux") == 0)
3676496f8fSPaul Mundt 		nmi_mode = NMI_MODE_AUX;
3776496f8fSPaul Mundt 	else if (strcmp(str, "masked") == 0)
3876496f8fSPaul Mundt 		nmi_mode = NMI_MODE_MASKED;
3976496f8fSPaul Mundt 	else if (strcmp(str, "any") == 0)
4076496f8fSPaul Mundt 		nmi_mode = NMI_MODE_ANY;
4176496f8fSPaul Mundt 	else {
4276496f8fSPaul Mundt 		nmi_mode = NMI_MODE_UNKNOWN;
4376496f8fSPaul Mundt 		pr_warning("Unknown NMI mode %s\n", str);
4476496f8fSPaul Mundt 	}
4576496f8fSPaul Mundt 
4676496f8fSPaul Mundt 	printk("Set NMI mode to %d\n", nmi_mode);
4776496f8fSPaul Mundt 	return 0;
4876496f8fSPaul Mundt }
4976496f8fSPaul Mundt early_param("nmi_mode", nmi_mode_setup);
5076496f8fSPaul Mundt 
5176496f8fSPaul Mundt void __init sdk7786_nmi_init(void)
5276496f8fSPaul Mundt {
5376496f8fSPaul Mundt 	unsigned int source, mask, tmp;
5476496f8fSPaul Mundt 
5576496f8fSPaul Mundt 	switch (nmi_mode) {
5676496f8fSPaul Mundt 	case NMI_MODE_MANUAL:
5776496f8fSPaul Mundt 		source = NMISR_MAN_NMI;
5876496f8fSPaul Mundt 		mask = NMIMR_MAN_NMIM;
5976496f8fSPaul Mundt 		break;
6076496f8fSPaul Mundt 	case NMI_MODE_AUX:
6176496f8fSPaul Mundt 		source = NMISR_AUX_NMI;
6276496f8fSPaul Mundt 		mask = NMIMR_AUX_NMIM;
6376496f8fSPaul Mundt 		break;
6476496f8fSPaul Mundt 	case NMI_MODE_ANY:
6576496f8fSPaul Mundt 		source = NMISR_MAN_NMI | NMISR_AUX_NMI;
6676496f8fSPaul Mundt 		mask = NMIMR_MAN_NMIM | NMIMR_AUX_NMIM;
6776496f8fSPaul Mundt 		break;
6876496f8fSPaul Mundt 	case NMI_MODE_MASKED:
6976496f8fSPaul Mundt 	case NMI_MODE_UNKNOWN:
7076496f8fSPaul Mundt 	default:
7176496f8fSPaul Mundt 		source = mask = 0;
7276496f8fSPaul Mundt 		break;
7376496f8fSPaul Mundt 	}
7476496f8fSPaul Mundt 
7576496f8fSPaul Mundt 	/* Set the NMI source */
7676496f8fSPaul Mundt 	tmp = fpga_read_reg(NMISR);
7776496f8fSPaul Mundt 	tmp &= ~NMISR_MASK;
7876496f8fSPaul Mundt 	tmp |= source;
7976496f8fSPaul Mundt 	fpga_write_reg(tmp, NMISR);
8076496f8fSPaul Mundt 
8176496f8fSPaul Mundt 	/* And the IRQ masking */
8276496f8fSPaul Mundt 	fpga_write_reg(NMIMR_MASK ^ mask, NMIMR);
8376496f8fSPaul Mundt }
84