pci-ip32.c 4.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2000, 2001 Keith M Wesolowski
 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
 */
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <asm/ip32/mace.h>
#include <asm/ip32/ip32_ints.h>

#undef DEBUG_MACE_PCI

/*
 * Handle errors from the bridge.  This includes master and target aborts,
 * various command and address errors, and the interrupt test.  This gets
 * registered on the bridge error irq.  It's conceivable that some of these
 * conditions warrant a panic.  Anybody care to say which ones?
 */
static irqreturn_t macepci_error(int irq, void *dev, struct pt_regs *regs)
{
	char s;
	unsigned int flags = mace->pci.error;
	unsigned int addr = mace->pci.error_addr;

	if (flags & MACEPCI_ERROR_MEMORY_ADDR)
		s = 'M';
	else if (flags & MACEPCI_ERROR_CONFIG_ADDR)
		s = 'C';
	else
		s = 'X';

	if (flags & MACEPCI_ERROR_MASTER_ABORT) {
		printk("MACEPCI: Master abort at 0x%08x (%c)\n", addr, s);
		flags &= ~MACEPCI_ERROR_MASTER_ABORT;
	}
	if (flags & MACEPCI_ERROR_TARGET_ABORT) {
		printk("MACEPCI: Target abort at 0x%08x (%c)\n", addr, s);
		flags &= ~MACEPCI_ERROR_TARGET_ABORT;
	}
	if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) {
		printk("MACEPCI: Data parity error at 0x%08x (%c)\n", addr, s);
		flags &= ~MACEPCI_ERROR_DATA_PARITY_ERR;
	}
	if (flags & MACEPCI_ERROR_RETRY_ERR) {
		printk("MACEPCI: Retry error at 0x%08x (%c)\n", addr, s);
		flags &= ~MACEPCI_ERROR_RETRY_ERR;
	}
	if (flags & MACEPCI_ERROR_ILLEGAL_CMD) {
		printk("MACEPCI: Illegal command at 0x%08x (%c)\n", addr, s);
		flags &= ~MACEPCI_ERROR_ILLEGAL_CMD;
	}
	if (flags & MACEPCI_ERROR_SYSTEM_ERR) {
		printk("MACEPCI: System error at 0x%08x (%c)\n", addr, s);
		flags &= ~MACEPCI_ERROR_SYSTEM_ERR;
	}
	if (flags & MACEPCI_ERROR_PARITY_ERR) {
		printk("MACEPCI: Parity error at 0x%08x (%c)\n", addr, s);
		flags &= ~MACEPCI_ERROR_PARITY_ERR;
	}
	if (flags & MACEPCI_ERROR_OVERRUN) {
		printk("MACEPCI: Overrun error at 0x%08x (%c)\n", addr, s);
		flags &= ~MACEPCI_ERROR_OVERRUN;
	}
	if (flags & MACEPCI_ERROR_SIG_TABORT) {
		printk("MACEPCI: Signaled target abort (clearing)\n");
		flags &= ~MACEPCI_ERROR_SIG_TABORT;
	}
	if (flags & MACEPCI_ERROR_INTERRUPT_TEST) {
		printk("MACEPCI: Interrupt test triggered (clearing)\n");
		flags &= ~MACEPCI_ERROR_INTERRUPT_TEST;
	}

	mace->pci.error = flags;

	return IRQ_HANDLED;
}


extern struct pci_ops mace_pci_ops;
#ifdef CONFIG_MIPS64
static struct resource mace_pci_mem_resource = {
	.name	= "SGI O2 PCI MEM",
	.start	= MACEPCI_HI_MEMORY,
	.end	= 0x2FFFFFFFFUL,
	.flags	= IORESOURCE_MEM,
};
static struct resource mace_pci_io_resource = {
	.name	= "SGI O2 PCI IO",
	.start	= 0x00000000UL,
	.end	= 0xffffffffUL,
	.flags	= IORESOURCE_IO,
};
#define MACE_PCI_MEM_OFFSET 0x200000000
#else
static struct resource mace_pci_mem_resource = {
	.name	= "SGI O2 PCI MEM",
	.start	= MACEPCI_LOW_MEMORY,
	.end	= MACEPCI_LOW_MEMORY + 0x2000000 - 1,
	.flags	= IORESOURCE_MEM,
};
static struct resource mace_pci_io_resource = {
	.name	= "SGI O2 PCI IO",
	.start	= 0x00000000,
	.end	= 0xFFFFFFFF,
	.flags	= IORESOURCE_IO,
};
#define MACE_PCI_MEM_OFFSET (MACEPCI_LOW_MEMORY - 0x80000000)
#endif
static struct pci_controller mace_pci_controller = {
	.pci_ops	= &mace_pci_ops,
	.mem_resource	= &mace_pci_mem_resource,
	.io_resource	= &mace_pci_io_resource,
	.iommu		= 0,
	.mem_offset	= MACE_PCI_MEM_OFFSET,
	.io_offset	= 0,
};

static int __init mace_init(void)
{
	PCIBIOS_MIN_IO = 0x1000;

	/* Clear any outstanding errors and enable interrupts */
	mace->pci.error_addr = 0;
	mace->pci.error = 0;
	mace->pci.control = 0xff008500;

	printk("MACE PCI rev %d\n", mace->pci.rev);

	BUG_ON(request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0,
			   "MACE PCI error", NULL));

	ioport_resource.end = mace_pci_io_resource.end;
	register_pci_controller(&mace_pci_controller);

	return 0;
}

arch_initcall(mace_init);