diff options
author | Brian Murphy <brm@murphy.dk> | 2007-08-21 22:34:16 +0200 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-10-11 23:46:00 +0100 |
commit | 1f21d2bde0046e959b53756f74d96dfd040a803b (patch) | |
tree | 5ca1a0319982f1e665e57f22bd1dae1d90b07e35 /arch/mips/pci | |
parent | 0caf583398309398ec05fc76bff15c711e9f936d (diff) |
[MIPS] Add back support for LASAT platforms
Signed-off-by: Brian Murphy <brian@murphy.dk>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/pci')
-rw-r--r-- | arch/mips/pci/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/pci/ops-nile4.c | 147 | ||||
-rw-r--r-- | arch/mips/pci/pci-lasat.c | 91 |
3 files changed, 240 insertions, 0 deletions
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 4ee6800e67e..ed0c07622ba 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -10,6 +10,7 @@ obj-y += pci.o obj-$(CONFIG_MIPS_BONITO64) += ops-bonito64.o obj-$(CONFIG_PCI_GT64XXX_PCI0) += ops-gt64xxx_pci0.o obj-$(CONFIG_MIPS_MSC) += ops-msc.o +obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o obj-$(CONFIG_MIPS_TX3927) += ops-tx3927.o obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o obj-$(CONFIG_NEC_CMBVR4133) += fixup-vr4133.o @@ -19,6 +20,7 @@ obj-$(CONFIG_MARKEINS) += ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o # These are still pretty much in the old state, watch, go blind. # obj-$(CONFIG_BASLER_EXCITE) += ops-titan.o pci-excite.o fixup-excite.o +obj-$(CONFIG_LASAT) += pci-lasat.o obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c new file mode 100644 index 00000000000..b7f0fb0210f --- /dev/null +++ b/arch/mips/pci/ops-nile4.c @@ -0,0 +1,147 @@ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <asm/bootinfo.h> + +#include <asm/lasat/lasat.h> +#include <asm/gt64120.h> +#include <asm/nile4.h> + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +#define LO(reg) (reg / 4) +#define HI(reg) (reg / 4 + 1) + +volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE; + +static DEFINE_SPINLOCK(nile4_pci_lock); + +static int nile4_pcibios_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, int where, u32 *val) +{ + unsigned char busnum = bus->number; + u32 adr, mask, err; + + if ((busnum == 0) && (PCI_SLOT(devfn) > 8)) + /* The addressing scheme chosen leaves room for just + * 8 devices on the first busnum (besides the PCI + * controller itself) */ + return PCIBIOS_DEVICE_NOT_FOUND; + + if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) { + /* Access controller registers directly */ + if (access_type == PCI_ACCESS_WRITE) { + vrc_pciregs[(0x200 + where) >> 2] = *val; + } else { + *val = vrc_pciregs[(0x200 + where) >> 2]; + } + return PCIBIOS_SUCCESSFUL; + } + + /* Temporarily map PCI Window 1 to config space */ + mask = vrc_pciregs[LO(NILE4_PCIINIT1)]; + vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0); + + /* Clear PCI Error register. This also clears the Error Type + * bits in the Control register */ + vrc_pciregs[LO(NILE4_PCIERR)] = 0; + vrc_pciregs[HI(NILE4_PCIERR)] = 0; + + /* Setup address */ + if (busnum == 0) + adr = + KSEG1ADDR(PCI_WINDOW1) + + ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8) + | (where & ~3)); + else + adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) | + (where & ~3); + + if (access_type == PCI_ACCESS_WRITE) + *(u32 *) adr = *val; + else + *val = *(u32 *) adr; + + /* Check for master or target abort */ + err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7; + + /* Restore PCI Window 1 */ + vrc_pciregs[LO(NILE4_PCIINIT1)] = mask; + + if (err) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + unsigned long flags; + u32 data = 0; + int err; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + spin_lock_irqsave(&nile4_pci_lock, flags); + err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data); + spin_unlock_irqrestore(&nile4_pci_lock, flags); + + if (err) + return err; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + unsigned long flags; + u32 data = 0; + int err; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + spin_lock_irqsave(&nile4_pci_lock, flags); + err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data); + spin_unlock_irqrestore(&nile4_pci_lock, flags); + + if (err) + return err; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else + data = val; + + if (nile4_pcibios_config_access + (PCI_ACCESS_WRITE, bus, devfn, where, &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops nile4_pci_ops = { + .read = nile4_pcibios_read, + .write = nile4_pcibios_write, +}; diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c new file mode 100644 index 00000000000..5abd5c7119b --- /dev/null +++ b/arch/mips/pci/pci-lasat.c @@ -0,0 +1,91 @@ +/* + * 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, 04 Keith M Wesolowski + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/types.h> +#include <asm/bootinfo.h> + +extern struct pci_ops nile4_pci_ops; +extern struct pci_ops gt64xxx_pci0_ops; +static struct resource lasat_pci_mem_resource = { + .name = "LASAT PCI MEM", + .start = 0x18000000, + .end = 0x19ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct resource lasat_pci_io_resource = { + .name = "LASAT PCI IO", + .start = 0x1a000000, + .end = 0x1bffffff, + .flags = IORESOURCE_IO, +}; + +static struct pci_controller lasat_pci_controller = { + .mem_resource = &lasat_pci_mem_resource, + .io_resource = &lasat_pci_io_resource, +}; + +static int __init lasat_pci_setup(void) +{ + printk(KERN_DEBUG "PCI: starting\n"); + + switch (mips_machtype) { + case MACH_LASAT_100: + lasat_pci_controller.pci_ops = >64xxx_pci0_ops; + break; + case MACH_LASAT_200: + lasat_pci_controller.pci_ops = &nile4_pci_ops; + break; + default: + panic("pcibios_init: mips_machtype incorrect"); + } + + register_pci_controller(&lasat_pci_controller); + + return 0; +} + +arch_initcall(lasat_pci_setup); + +#define LASATINT_ETH1 0 +#define LASATINT_ETH0 1 +#define LASATINT_HDC 2 +#define LASATINT_COMP 3 +#define LASATINT_HDLC 4 +#define LASATINT_PCIA 5 +#define LASATINT_PCIB 6 +#define LASATINT_PCIC 7 +#define LASATINT_PCID 8 + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + switch (slot) { + case 1: + case 2: + case 3: + return LASATINT_PCIA + (((slot-1) + (pin-1)) % 4); + case 4: + return LASATINT_ETH1; /* Ethernet 1 (LAN 2) */ + case 5: + return LASATINT_ETH0; /* Ethernet 0 (LAN 1) */ + case 6: + return LASATINT_HDC; /* IDE controller */ + default: + return 0xff; /* Illegal */ + } + + return -1; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} |