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