1aaf9128aSKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
276496f8fSPaul Mundt /*
376496f8fSPaul Mundt * SDK7786 FPGA NMI Support.
476496f8fSPaul Mundt *
576496f8fSPaul Mundt * Copyright (C) 2010 Paul Mundt
676496f8fSPaul Mundt */
776496f8fSPaul Mundt #include <linux/init.h>
876496f8fSPaul Mundt #include <linux/kernel.h>
976496f8fSPaul Mundt #include <linux/string.h>
1076496f8fSPaul Mundt #include <mach/fpga.h>
1176496f8fSPaul Mundt
1276496f8fSPaul Mundt enum {
1376496f8fSPaul Mundt NMI_MODE_MANUAL,
1476496f8fSPaul Mundt NMI_MODE_AUX,
1576496f8fSPaul Mundt NMI_MODE_MASKED,
1676496f8fSPaul Mundt NMI_MODE_ANY,
1776496f8fSPaul Mundt NMI_MODE_UNKNOWN,
1876496f8fSPaul Mundt };
1976496f8fSPaul Mundt
2076496f8fSPaul Mundt /*
2176496f8fSPaul Mundt * Default to the manual NMI switch.
2276496f8fSPaul Mundt */
2376496f8fSPaul Mundt static unsigned int __initdata nmi_mode = NMI_MODE_ANY;
2476496f8fSPaul Mundt
nmi_mode_setup(char * str)2576496f8fSPaul Mundt static int __init nmi_mode_setup(char *str)
2676496f8fSPaul Mundt {
2776496f8fSPaul Mundt if (!str)
2876496f8fSPaul Mundt return 0;
2976496f8fSPaul Mundt
3076496f8fSPaul Mundt if (strcmp(str, "manual") == 0)
3176496f8fSPaul Mundt nmi_mode = NMI_MODE_MANUAL;
3276496f8fSPaul Mundt else if (strcmp(str, "aux") == 0)
3376496f8fSPaul Mundt nmi_mode = NMI_MODE_AUX;
3476496f8fSPaul Mundt else if (strcmp(str, "masked") == 0)
3576496f8fSPaul Mundt nmi_mode = NMI_MODE_MASKED;
3676496f8fSPaul Mundt else if (strcmp(str, "any") == 0)
3776496f8fSPaul Mundt nmi_mode = NMI_MODE_ANY;
3876496f8fSPaul Mundt else {
3976496f8fSPaul Mundt nmi_mode = NMI_MODE_UNKNOWN;
40*6d80f20cSKefeng Wang pr_warn("Unknown NMI mode %s\n", str);
4176496f8fSPaul Mundt }
4276496f8fSPaul Mundt
4376496f8fSPaul Mundt printk("Set NMI mode to %d\n", nmi_mode);
4476496f8fSPaul Mundt return 0;
4576496f8fSPaul Mundt }
4676496f8fSPaul Mundt early_param("nmi_mode", nmi_mode_setup);
4776496f8fSPaul Mundt
sdk7786_nmi_init(void)4876496f8fSPaul Mundt void __init sdk7786_nmi_init(void)
4976496f8fSPaul Mundt {
5076496f8fSPaul Mundt unsigned int source, mask, tmp;
5176496f8fSPaul Mundt
5276496f8fSPaul Mundt switch (nmi_mode) {
5376496f8fSPaul Mundt case NMI_MODE_MANUAL:
5476496f8fSPaul Mundt source = NMISR_MAN_NMI;
5576496f8fSPaul Mundt mask = NMIMR_MAN_NMIM;
5676496f8fSPaul Mundt break;
5776496f8fSPaul Mundt case NMI_MODE_AUX:
5876496f8fSPaul Mundt source = NMISR_AUX_NMI;
5976496f8fSPaul Mundt mask = NMIMR_AUX_NMIM;
6076496f8fSPaul Mundt break;
6176496f8fSPaul Mundt case NMI_MODE_ANY:
6276496f8fSPaul Mundt source = NMISR_MAN_NMI | NMISR_AUX_NMI;
6376496f8fSPaul Mundt mask = NMIMR_MAN_NMIM | NMIMR_AUX_NMIM;
6476496f8fSPaul Mundt break;
6576496f8fSPaul Mundt case NMI_MODE_MASKED:
6676496f8fSPaul Mundt case NMI_MODE_UNKNOWN:
6776496f8fSPaul Mundt default:
6876496f8fSPaul Mundt source = mask = 0;
6976496f8fSPaul Mundt break;
7076496f8fSPaul Mundt }
7176496f8fSPaul Mundt
7276496f8fSPaul Mundt /* Set the NMI source */
7376496f8fSPaul Mundt tmp = fpga_read_reg(NMISR);
7476496f8fSPaul Mundt tmp &= ~NMISR_MASK;
7576496f8fSPaul Mundt tmp |= source;
7676496f8fSPaul Mundt fpga_write_reg(tmp, NMISR);
7776496f8fSPaul Mundt
7876496f8fSPaul Mundt /* And the IRQ masking */
7976496f8fSPaul Mundt fpga_write_reg(NMIMR_MASK ^ mask, NMIMR);
8076496f8fSPaul Mundt }
81