X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-ixp2000%2Fpci.c;h=5a09a90c08fb7f3e36df1a2f2967e01616a6ea5e;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=d08cebe0051752e9a148b73d8c26d773716560b7;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c index d08cebe00..5a09a90c0 100644 --- a/arch/arm/mach-ixp2000/pci.c +++ b/arch/arm/mach-ixp2000/pci.c @@ -28,16 +28,15 @@ #include #include #include -#include #include #include -static int pci_master_aborts = 0; +static volatile int pci_master_aborts = 0; static int clear_master_aborts(void); -static u32 * +u32 * ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where) { u32 *paddress; @@ -142,23 +141,24 @@ int ixp2000_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_re { volatile u32 temp; + unsigned long flags; pci_master_aborts = 1; - cli(); + local_irq_save(flags); temp = *(IXP2000_PCI_CONTROL); if (temp & ((1 << 8) | (1 << 5))) { - *(IXP2000_PCI_CONTROL) = temp; + ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp); } temp = *(IXP2000_PCI_CMDSTAT); if (temp & (1 << 29)) { while (temp & (1 << 29)) { - *(IXP2000_PCI_CMDSTAT) = temp; + ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp); temp = *(IXP2000_PCI_CMDSTAT); } } - sti(); + local_irq_restore(flags); /* * If it was an imprecise abort, then we need to correct the @@ -174,21 +174,22 @@ int clear_master_aborts(void) { volatile u32 temp; + unsigned long flags; - cli(); + local_irq_save(flags); temp = *(IXP2000_PCI_CONTROL); - if (temp & ((1 << 8) | (1 << 5))) { - *(IXP2000_PCI_CONTROL) = temp; + if (temp & ((1 << 8) | (1 << 5))) { + ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp); } temp = *(IXP2000_PCI_CMDSTAT); if (temp & (1 << 29)) { while (temp & (1 << 29)) { - *(IXP2000_PCI_CMDSTAT) = temp; + ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp); temp = *(IXP2000_PCI_CMDSTAT); } } - sti(); + local_irq_restore(flags); return 0; } @@ -196,6 +197,19 @@ clear_master_aborts(void) void __init ixp2000_pci_preinit(void) { +#ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO + /* + * Configure the PCI unit to properly byteswap I/O transactions, + * and verify that it worked. + */ + ixp2000_reg_write(IXP2000_PCI_CONTROL, + (*IXP2000_PCI_CONTROL | PCI_CONTROL_IEE)); + + if ((*IXP2000_PCI_CONTROL & PCI_CONTROL_IEE) == 0) + panic("IXP2000: PCI I/O is broken on this ixp model, and " + "the needed workaround has not been configured in"); +#endif + hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS, "PCI config cycle to non-existent device"); } @@ -206,15 +220,15 @@ ixp2000_pci_preinit(void) * use our own resource space. */ static struct resource ixp2000_pci_mem_space = { - .start = 0x00000000, + .start = 0xe0000000, .end = 0xffffffff, .flags = IORESOURCE_MEM, .name = "PCI Mem Space" }; static struct resource ixp2000_pci_io_space = { - .start = 0x00000000, - .end = 0xffffffff, + .start = 0x00010000, + .end = 0x0001ffff, .flags = IORESOURCE_IO, .name = "PCI I/O Space" };