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) 2000, 2001 Keith M Wesolowski 71da177e4SLinus Torvalds * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds #include <linux/config.h> 101da177e4SLinus Torvalds #include <linux/kernel.h> 111da177e4SLinus Torvalds #include <linux/init.h> 121da177e4SLinus Torvalds #include <linux/interrupt.h> 131da177e4SLinus Torvalds #include <linux/pci.h> 141da177e4SLinus Torvalds #include <linux/types.h> 151da177e4SLinus Torvalds #include <asm/ip32/mace.h> 161da177e4SLinus Torvalds #include <asm/ip32/ip32_ints.h> 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds #undef DEBUG_MACE_PCI 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds /* 211da177e4SLinus Torvalds * Handle errors from the bridge. This includes master and target aborts, 221da177e4SLinus Torvalds * various command and address errors, and the interrupt test. This gets 231da177e4SLinus Torvalds * registered on the bridge error irq. It's conceivable that some of these 241da177e4SLinus Torvalds * conditions warrant a panic. Anybody care to say which ones? 251da177e4SLinus Torvalds */ 261da177e4SLinus Torvalds static irqreturn_t macepci_error(int irq, void *dev, struct pt_regs *regs) 271da177e4SLinus Torvalds { 281da177e4SLinus Torvalds char s; 291da177e4SLinus Torvalds unsigned int flags = mace->pci.error; 301da177e4SLinus Torvalds unsigned int addr = mace->pci.error_addr; 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_MEMORY_ADDR) 331da177e4SLinus Torvalds s = 'M'; 341da177e4SLinus Torvalds else if (flags & MACEPCI_ERROR_CONFIG_ADDR) 351da177e4SLinus Torvalds s = 'C'; 361da177e4SLinus Torvalds else 371da177e4SLinus Torvalds s = 'X'; 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_MASTER_ABORT) { 401da177e4SLinus Torvalds printk("MACEPCI: Master abort at 0x%08x (%c)\n", addr, s); 411da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_MASTER_ABORT; 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_TARGET_ABORT) { 441da177e4SLinus Torvalds printk("MACEPCI: Target abort at 0x%08x (%c)\n", addr, s); 451da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_TARGET_ABORT; 461da177e4SLinus Torvalds } 471da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) { 481da177e4SLinus Torvalds printk("MACEPCI: Data parity error at 0x%08x (%c)\n", addr, s); 491da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_DATA_PARITY_ERR; 501da177e4SLinus Torvalds } 511da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_RETRY_ERR) { 521da177e4SLinus Torvalds printk("MACEPCI: Retry error at 0x%08x (%c)\n", addr, s); 531da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_RETRY_ERR; 541da177e4SLinus Torvalds } 551da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_ILLEGAL_CMD) { 561da177e4SLinus Torvalds printk("MACEPCI: Illegal command at 0x%08x (%c)\n", addr, s); 571da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_ILLEGAL_CMD; 581da177e4SLinus Torvalds } 591da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_SYSTEM_ERR) { 601da177e4SLinus Torvalds printk("MACEPCI: System error at 0x%08x (%c)\n", addr, s); 611da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_SYSTEM_ERR; 621da177e4SLinus Torvalds } 631da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_PARITY_ERR) { 641da177e4SLinus Torvalds printk("MACEPCI: Parity error at 0x%08x (%c)\n", addr, s); 651da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_PARITY_ERR; 661da177e4SLinus Torvalds } 671da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_OVERRUN) { 681da177e4SLinus Torvalds printk("MACEPCI: Overrun error at 0x%08x (%c)\n", addr, s); 691da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_OVERRUN; 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_SIG_TABORT) { 721da177e4SLinus Torvalds printk("MACEPCI: Signaled target abort (clearing)\n"); 731da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_SIG_TABORT; 741da177e4SLinus Torvalds } 751da177e4SLinus Torvalds if (flags & MACEPCI_ERROR_INTERRUPT_TEST) { 761da177e4SLinus Torvalds printk("MACEPCI: Interrupt test triggered (clearing)\n"); 771da177e4SLinus Torvalds flags &= ~MACEPCI_ERROR_INTERRUPT_TEST; 781da177e4SLinus Torvalds } 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds mace->pci.error = flags; 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds return IRQ_HANDLED; 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds extern struct pci_ops mace_pci_ops; 87875d43e7SRalf Baechle #ifdef CONFIG_64BIT 881da177e4SLinus Torvalds static struct resource mace_pci_mem_resource = { 891da177e4SLinus Torvalds .name = "SGI O2 PCI MEM", 901da177e4SLinus Torvalds .start = MACEPCI_HI_MEMORY, 911da177e4SLinus Torvalds .end = 0x2FFFFFFFFUL, 921da177e4SLinus Torvalds .flags = IORESOURCE_MEM, 931da177e4SLinus Torvalds }; 941da177e4SLinus Torvalds static struct resource mace_pci_io_resource = { 951da177e4SLinus Torvalds .name = "SGI O2 PCI IO", 961da177e4SLinus Torvalds .start = 0x00000000UL, 971da177e4SLinus Torvalds .end = 0xffffffffUL, 981da177e4SLinus Torvalds .flags = IORESOURCE_IO, 991da177e4SLinus Torvalds }; 1001da177e4SLinus Torvalds #define MACE_PCI_MEM_OFFSET 0x200000000 1011da177e4SLinus Torvalds #else 1021da177e4SLinus Torvalds static struct resource mace_pci_mem_resource = { 1031da177e4SLinus Torvalds .name = "SGI O2 PCI MEM", 1041da177e4SLinus Torvalds .start = MACEPCI_LOW_MEMORY, 1051da177e4SLinus Torvalds .end = MACEPCI_LOW_MEMORY + 0x2000000 - 1, 1061da177e4SLinus Torvalds .flags = IORESOURCE_MEM, 1071da177e4SLinus Torvalds }; 1081da177e4SLinus Torvalds static struct resource mace_pci_io_resource = { 1091da177e4SLinus Torvalds .name = "SGI O2 PCI IO", 1101da177e4SLinus Torvalds .start = 0x00000000, 1111da177e4SLinus Torvalds .end = 0xFFFFFFFF, 1121da177e4SLinus Torvalds .flags = IORESOURCE_IO, 1131da177e4SLinus Torvalds }; 1141da177e4SLinus Torvalds #define MACE_PCI_MEM_OFFSET (MACEPCI_LOW_MEMORY - 0x80000000) 1151da177e4SLinus Torvalds #endif 1161da177e4SLinus Torvalds static struct pci_controller mace_pci_controller = { 1171da177e4SLinus Torvalds .pci_ops = &mace_pci_ops, 1181da177e4SLinus Torvalds .mem_resource = &mace_pci_mem_resource, 1191da177e4SLinus Torvalds .io_resource = &mace_pci_io_resource, 1201da177e4SLinus Torvalds .iommu = 0, 1211da177e4SLinus Torvalds .mem_offset = MACE_PCI_MEM_OFFSET, 1221da177e4SLinus Torvalds .io_offset = 0, 1231da177e4SLinus Torvalds }; 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds static int __init mace_init(void) 1261da177e4SLinus Torvalds { 1271da177e4SLinus Torvalds PCIBIOS_MIN_IO = 0x1000; 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds /* Clear any outstanding errors and enable interrupts */ 1301da177e4SLinus Torvalds mace->pci.error_addr = 0; 1311da177e4SLinus Torvalds mace->pci.error = 0; 1321da177e4SLinus Torvalds mace->pci.control = 0xff008500; 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds printk("MACE PCI rev %d\n", mace->pci.rev); 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds BUG_ON(request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0, 1371da177e4SLinus Torvalds "MACE PCI error", NULL)); 1381da177e4SLinus Torvalds 139dd193261SThiemo Seufer iomem_resource = mace_pci_mem_resource; 140dd193261SThiemo Seufer ioport_resource = mace_pci_io_resource; 141dd193261SThiemo Seufer 1421da177e4SLinus Torvalds register_pci_controller(&mace_pci_controller); 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds return 0; 1451da177e4SLinus Torvalds } 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds arch_initcall(mace_init); 148