162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * SDK7786 FPGA NMI Support. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2010 Paul Mundt 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/init.h> 862306a36Sopenharmony_ci#include <linux/kernel.h> 962306a36Sopenharmony_ci#include <linux/string.h> 1062306a36Sopenharmony_ci#include <mach/fpga.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cienum { 1362306a36Sopenharmony_ci NMI_MODE_MANUAL, 1462306a36Sopenharmony_ci NMI_MODE_AUX, 1562306a36Sopenharmony_ci NMI_MODE_MASKED, 1662306a36Sopenharmony_ci NMI_MODE_ANY, 1762306a36Sopenharmony_ci NMI_MODE_UNKNOWN, 1862306a36Sopenharmony_ci}; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* 2162306a36Sopenharmony_ci * Default to the manual NMI switch. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_cistatic unsigned int __initdata nmi_mode = NMI_MODE_ANY; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic int __init nmi_mode_setup(char *str) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci if (!str) 2862306a36Sopenharmony_ci return 0; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci if (strcmp(str, "manual") == 0) 3162306a36Sopenharmony_ci nmi_mode = NMI_MODE_MANUAL; 3262306a36Sopenharmony_ci else if (strcmp(str, "aux") == 0) 3362306a36Sopenharmony_ci nmi_mode = NMI_MODE_AUX; 3462306a36Sopenharmony_ci else if (strcmp(str, "masked") == 0) 3562306a36Sopenharmony_ci nmi_mode = NMI_MODE_MASKED; 3662306a36Sopenharmony_ci else if (strcmp(str, "any") == 0) 3762306a36Sopenharmony_ci nmi_mode = NMI_MODE_ANY; 3862306a36Sopenharmony_ci else { 3962306a36Sopenharmony_ci nmi_mode = NMI_MODE_UNKNOWN; 4062306a36Sopenharmony_ci pr_warn("Unknown NMI mode %s\n", str); 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci printk("Set NMI mode to %d\n", nmi_mode); 4462306a36Sopenharmony_ci return 0; 4562306a36Sopenharmony_ci} 4662306a36Sopenharmony_ciearly_param("nmi_mode", nmi_mode_setup); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_civoid __init sdk7786_nmi_init(void) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci unsigned int source, mask, tmp; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci switch (nmi_mode) { 5362306a36Sopenharmony_ci case NMI_MODE_MANUAL: 5462306a36Sopenharmony_ci source = NMISR_MAN_NMI; 5562306a36Sopenharmony_ci mask = NMIMR_MAN_NMIM; 5662306a36Sopenharmony_ci break; 5762306a36Sopenharmony_ci case NMI_MODE_AUX: 5862306a36Sopenharmony_ci source = NMISR_AUX_NMI; 5962306a36Sopenharmony_ci mask = NMIMR_AUX_NMIM; 6062306a36Sopenharmony_ci break; 6162306a36Sopenharmony_ci case NMI_MODE_ANY: 6262306a36Sopenharmony_ci source = NMISR_MAN_NMI | NMISR_AUX_NMI; 6362306a36Sopenharmony_ci mask = NMIMR_MAN_NMIM | NMIMR_AUX_NMIM; 6462306a36Sopenharmony_ci break; 6562306a36Sopenharmony_ci case NMI_MODE_MASKED: 6662306a36Sopenharmony_ci case NMI_MODE_UNKNOWN: 6762306a36Sopenharmony_ci default: 6862306a36Sopenharmony_ci source = mask = 0; 6962306a36Sopenharmony_ci break; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* Set the NMI source */ 7362306a36Sopenharmony_ci tmp = fpga_read_reg(NMISR); 7462306a36Sopenharmony_ci tmp &= ~NMISR_MASK; 7562306a36Sopenharmony_ci tmp |= source; 7662306a36Sopenharmony_ci fpga_write_reg(tmp, NMISR); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* And the IRQ masking */ 7962306a36Sopenharmony_ci fpga_write_reg(NMIMR_MASK ^ mask, NMIMR); 8062306a36Sopenharmony_ci} 81