pci-ip32.c 4.1 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
/*
 * 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/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?
 */
25
static irqreturn_t macepci_error(int irq, void *dev)
L
Linus Torvalds 已提交
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
{
	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;
86
#ifdef CONFIG_64BIT
L
Linus Torvalds 已提交
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
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,
T
Thomas Bogendoerfer 已提交
122
	.io_map_base	= CKSEG1ADDR(MACEPCI_LOW_IO),
L
Linus Torvalds 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
};

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));

T
Thomas Bogendoerfer 已提交
139 140
	/* extend memory resources */
	iomem_resource.end = mace_pci_mem_resource.end;
T
Thiemo Seufer 已提交
141 142
	ioport_resource = mace_pci_io_resource;

L
Linus Torvalds 已提交
143 144 145 146 147 148
	register_pci_controller(&mace_pci_controller);

	return 0;
}

arch_initcall(mace_init);