11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4SLinus Torvalds * for more details. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (C) 2001, 2003 Keith M Wesolowski 71da177e4SLinus Torvalds * Copyright (C) 2005 Ilya A. Volynets <ilya@total-knowledge.com> 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds #include <linux/types.h> 101da177e4SLinus Torvalds #include <linux/init.h> 111da177e4SLinus Torvalds #include <linux/kernel.h> 121da177e4SLinus Torvalds #include <linux/interrupt.h> 13*26dd3e4fSPaul Gortmaker #include <linux/export.h> 141da177e4SLinus Torvalds #include <asm/bootinfo.h> 151da177e4SLinus Torvalds #include <asm/io.h> 161da177e4SLinus Torvalds #include <asm/mipsregs.h> 171da177e4SLinus Torvalds #include <asm/page.h> 181da177e4SLinus Torvalds #include <asm/ip32/crime.h> 191da177e4SLinus Torvalds #include <asm/ip32/mace.h> 201da177e4SLinus Torvalds 2159f145d2SArnaud Giersch struct sgi_crime __iomem *crime; 2259f145d2SArnaud Giersch struct sgi_mace __iomem *mace; 231da177e4SLinus Torvalds 2419ce1cfbSArnaud Giersch EXPORT_SYMBOL_GPL(mace); 2519ce1cfbSArnaud Giersch 261da177e4SLinus Torvalds void __init crime_init(void) 271da177e4SLinus Torvalds { 281da177e4SLinus Torvalds unsigned int id, rev; 291da177e4SLinus Torvalds const int field = 2 * sizeof(unsigned long); 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds set_io_port_base((unsigned long) ioremap(MACEPCI_LOW_IO, 0x2000000)); 321da177e4SLinus Torvalds crime = ioremap(CRIME_BASE, sizeof(struct sgi_crime)); 331da177e4SLinus Torvalds mace = ioremap(MACE_BASE, sizeof(struct sgi_mace)); 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds id = crime->id; 361da177e4SLinus Torvalds rev = id & CRIME_ID_REV; 371da177e4SLinus Torvalds id = (id & CRIME_ID_IDBITS) >> 4; 381da177e4SLinus Torvalds printk(KERN_INFO "CRIME id %1x rev %d at 0x%0*lx\n", 391da177e4SLinus Torvalds id, rev, field, (unsigned long) CRIME_BASE); 401da177e4SLinus Torvalds } 411da177e4SLinus Torvalds 42937a8015SRalf Baechle irqreturn_t crime_memerr_intr(unsigned int irq, void *dev_id) 431da177e4SLinus Torvalds { 441da177e4SLinus Torvalds unsigned long stat, addr; 451da177e4SLinus Torvalds int fatal = 0; 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds stat = crime->mem_error_stat & CRIME_MEM_ERROR_STAT_MASK; 481da177e4SLinus Torvalds addr = crime->mem_error_addr & CRIME_MEM_ERROR_ADDR_MASK; 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds printk("CRIME memory error at 0x%08lx ST 0x%08lx<", addr, stat); 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_INV) 531da177e4SLinus Torvalds printk("INV,"); 541da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_ECC) { 551da177e4SLinus Torvalds unsigned long ecc_syn = 561da177e4SLinus Torvalds crime->mem_ecc_syn & CRIME_MEM_ERROR_ECC_SYN_MASK; 571da177e4SLinus Torvalds unsigned long ecc_gen = 581da177e4SLinus Torvalds crime->mem_ecc_chk & CRIME_MEM_ERROR_ECC_CHK_MASK; 591da177e4SLinus Torvalds printk("ECC,SYN=0x%08lx,GEN=0x%08lx,", ecc_syn, ecc_gen); 601da177e4SLinus Torvalds } 611da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_MULTIPLE) { 621da177e4SLinus Torvalds fatal = 1; 631da177e4SLinus Torvalds printk("MULTIPLE,"); 641da177e4SLinus Torvalds } 651da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_HARD_ERR) { 661da177e4SLinus Torvalds fatal = 1; 671da177e4SLinus Torvalds printk("HARD,"); 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_SOFT_ERR) 701da177e4SLinus Torvalds printk("SOFT,"); 711da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_CPU_ACCESS) 721da177e4SLinus Torvalds printk("CPU,"); 731da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_VICE_ACCESS) 741da177e4SLinus Torvalds printk("VICE,"); 751da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_GBE_ACCESS) 761da177e4SLinus Torvalds printk("GBE,"); 771da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_RE_ACCESS) 781da177e4SLinus Torvalds printk("RE,REID=0x%02lx,", (stat & CRIME_MEM_ERROR_RE_ID)>>8); 791da177e4SLinus Torvalds if (stat & CRIME_MEM_ERROR_MACE_ACCESS) 801da177e4SLinus Torvalds printk("MACE,MACEID=0x%02lx,", stat & CRIME_MEM_ERROR_MACE_ID); 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds crime->mem_error_stat = 0; 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds if (fatal) { 851da177e4SLinus Torvalds printk("FATAL>\n"); 861da177e4SLinus Torvalds panic("Fatal memory error."); 871da177e4SLinus Torvalds } else 881da177e4SLinus Torvalds printk("NONFATAL>\n"); 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds return IRQ_HANDLED; 911da177e4SLinus Torvalds } 921da177e4SLinus Torvalds 93937a8015SRalf Baechle irqreturn_t crime_cpuerr_intr(unsigned int irq, void *dev_id) 941da177e4SLinus Torvalds { 951da177e4SLinus Torvalds unsigned long stat = crime->cpu_error_stat & CRIME_CPU_ERROR_MASK; 961da177e4SLinus Torvalds unsigned long addr = crime->cpu_error_addr & CRIME_CPU_ERROR_ADDR_MASK; 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds addr <<= 2; 991da177e4SLinus Torvalds printk("CRIME CPU error at 0x%09lx status 0x%08lx\n", addr, stat); 1001da177e4SLinus Torvalds crime->cpu_error_stat = 0; 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds return IRQ_HANDLED; 1031da177e4SLinus Torvalds } 104