diff options
Diffstat (limited to 'arch/mips/ddb5074/pci.c')
-rw-r--r-- | arch/mips/ddb5074/pci.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/arch/mips/ddb5074/pci.c b/arch/mips/ddb5074/pci.c new file mode 100644 index 000000000..2fcd3fbf7 --- /dev/null +++ b/arch/mips/ddb5074/pci.c @@ -0,0 +1,320 @@ +/* + * arch/mips/ddb5074/pci.c -- NEC DDB Vrc-5074 PCI access routines + * + * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com> + * Albert Dorofeev <albert@sonycom.com> + * Sony Suprastructure Center Europe (SUPC-E), Brussels + * + * $Id$ + */ + +#include <linux/init.h> +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/ioport.h> +#include <asm-mips/nile4.h> + + +static u32 nile4_pre_pci_access0(int slot_num) +{ + u32 pci_addr = 0; + u32 virt_addr = NILE4_PCI_CFG_BASE; + + /* Set window 1 address 8000000 - 64 bit - 2 MB (PCI config space) */ + nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x00200000, 64, 0, 0); + if (slot_num > 2) + pci_addr = 0x00040000 << slot_num; + else + virt_addr += 0x00040000 << slot_num; + nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr); + return virt_addr; +} + +static void nile4_post_pci_access0(void) +{ + /* Set window 1 back to address 8000000 - 64 bit - 128 MB (PCI IO space) */ + nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE), 0x08000000, 64, + 1, 1); + nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0); +} + + +static int nile4_pci_read_config_dword( struct pci_dev *dev, + int where, u32 *val) +{ + int slot_num, func_num; + u32 base; + + /* + * For starters let's do configuration cycle 0 only (one bus only) + */ + if (dev->bus->number) + return PCIBIOS_FUNC_NOT_SUPPORTED; + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + if (slot_num == 5) { + /* + * This is Nile 4 and it will crash if we access it like other + * devices + */ + *val = nile4_in32(NILE4_PCI_BASE + where); + return PCIBIOS_SUCCESSFUL; + } + base = nile4_pre_pci_access0(slot_num); + *val = *((volatile u32 *)(base + (func_num << 8) + (where & 0xfc))); + nile4_post_pci_access0(); + return PCIBIOS_SUCCESSFUL; +} + +static int nile4_pci_write_config_dword(struct pci_dev *dev, int where, + u32 val) +{ + int slot_num, func_num; + u32 base; + + /* + * For starters let's do configuration cycle 0 only (one bus only) + */ + if (dev->bus->number) + return PCIBIOS_FUNC_NOT_SUPPORTED; + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + if (slot_num == 5) { + /* + * This is Nile 4 and it will crash if we access it like other + * devices + */ + nile4_out32(NILE4_PCI_BASE + where, val); + return PCIBIOS_SUCCESSFUL; + } + base = nile4_pre_pci_access0(slot_num); + *((volatile u32 *)(base + (func_num << 8) + (where & 0xfc))) = val; + nile4_post_pci_access0(); + return PCIBIOS_SUCCESSFUL; +} + +static int nile4_pci_read_config_word(struct pci_dev *dev, int where, u16 *val) +{ + int status; + u32 result; + + status = nile4_pci_read_config_dword(dev, where, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + if (where & 2) + result >>= 16; + *val = result & 0xffff; + return PCIBIOS_SUCCESSFUL; +} + +static int nile4_pci_read_config_byte(struct pci_dev *dev, int where, u8 *val) +{ + int status; + u32 result; + + status = nile4_pci_read_config_dword(dev, where, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + if (where & 1) + result >>= 8; + if (where & 2) + result >>= 16; + *val = result & 0xff; + return PCIBIOS_SUCCESSFUL; +} + +static int nile4_pci_write_config_word(struct pci_dev *dev, int where, u16 val) +{ + int status, shift = 0; + u32 result; + + status = nile4_pci_read_config_dword(dev, where, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + if (where & 2) + shift += 16; + result &= ~(0xffff << shift); + result |= val << shift; + return nile4_pci_write_config_dword(dev, where, result); +} + +static int nile4_pci_write_config_byte( struct pci_dev *dev, int where, u8 val) +{ + int status, shift = 0; + u32 result; + + status = nile4_pci_read_config_dword(dev, where, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + if (where & 2) + shift += 16; + if (where & 1) + shift += 8; + result &= ~(0xff << shift); + result |= val << shift; + return nile4_pci_write_config_dword(dev, where, result); +} + +struct pci_ops nile4_pci_ops = { + nile4_pci_read_config_byte, + nile4_pci_read_config_word, + nile4_pci_read_config_dword, + nile4_pci_write_config_byte, + nile4_pci_write_config_word, + nile4_pci_write_config_dword +}; + + +static void __init pcibios_claim_resources(struct pci_bus *bus) +{ + struct pci_dev *dev; + int idx; + + while (bus) { + for (dev=bus->devices; dev; dev=dev->sibling) { + for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) { + struct resource *r = &dev->resource[idx]; + struct resource *pr; + if (!r->start) + continue; + pr = pci_find_parent_resource(dev, r); + if (!pr || request_resource(pr, r) < 0) { + printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", idx, dev->name); + /* We probably should disable the region, shouldn't we? */ + } + } + } + if (bus->children) + pcibios_claim_resources(bus->children); + bus = bus->next; + } +} + + +void pcibios_init(void) +{ + printk("PCI: Probing PCI hardware\n"); + ioport_resource.end = 0x1ffffff; + pci_scan_bus(0, &nile4_pci_ops, NULL); + pcibios_claim_resources(pci_root); + +#if 0 + { + char buf[PAGE_SIZE]; + printk("*** PCI Devices ***\n"); + get_pci_list(buf); + printk(buf); + printk("*** PCI I/O Space ***\n"); + buf[0] = '\0'; + get_ioport_list(buf); + printk(buf); + printk("*** PCI Memory ***\n"); + buf[0] = '\0'; + get_mem_list(buf); + printk(buf); + } +#endif +} + +void pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_dev *dev; + extern struct pci_dev *pci_pmu; /* for LEDs D2 and D3 */ + u8 t8; + + /* + * FIXME: PMON doesn't autoconfigure the PCI devices + * For now we just hardcode them for our configuration + */ + for (dev = bus->devices; dev; dev = dev->sibling) { + int slot_num, func_num; + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + printk(" Device %2d: ", slot_num); + switch (slot_num) { + case 0: + printk("[onboard] Acer Labs M1533 Aladdin IV\n"); + dev->irq = nile4_to_irq(NILE4_INT_INTE); + break; + case 1: + printk("[onboard] DEC DC21140\n"); + dev->irq = nile4_to_irq(NILE4_INT_INTA); + dev->resource[0].start = 0x100000; + dev->resource[0].end = dev->resource[0].start+0x7f; + nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + dev->resource[0].start); + dev->resource[1].start = 0x1000000; + dev->resource[1].end = dev->resource[1].start+0x7f; + nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + dev->resource[1].start); + break; + case 2: + printk("[slot 1] Realtek 8029\n"); + dev->irq = nile4_to_irq(NILE4_INT_INTA); + dev->resource[0].start = 0x800000; + dev->resource[0].end = dev->resource[0].start+0x1f; + nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + dev->resource[0].start); + break; + case 3: + printk("[slot 2] DEC DC21140 (#2)\n"); + dev->irq = nile4_to_irq(NILE4_INT_INTB); + dev->resource[0].start = 0x1000000; + dev->resource[0].end = dev->resource[0].start+0x7f; + nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + dev->resource[0].start); + dev->resource[1].start = 0x4000000; + dev->resource[1].end = dev->resource[1].start+0x7f; + nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + dev->resource[1].start); + break; + case 4: + printk("[slot 3] Promise Technology IDE UltraDMA/33"); + printk(" Or 3Com 3c905 :-)\n"); + dev->irq = nile4_to_irq(NILE4_INT_INTC); + dev->resource[0].start = 0x1800000; + dev->resource[0].end = dev->resource[0].start+0x7fffff; + nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + dev->resource[0].start); + break; + case 10: + printk("[onboard] Acer Labs M7101 PMU\n"); + pci_pmu = dev; + /* Program the lines for LEDs D2 and D3 to output */ + nile4_pci_read_config_byte(dev, 0x7d, &t8); + t8 |= 0xc0; + nile4_pci_write_config_byte(dev, 0x7d, t8); + /* Turn LEDs D2 and D3 off */ + nile4_pci_read_config_byte(dev, 0x7e, &t8); + t8 |= 0xc0; + nile4_pci_write_config_byte(dev, 0x7e, t8); + break; + case 13: + printk("[onboard] Acer Labs M5237 USB\n"); + dev->irq = nile4_to_irq(NILE4_INT_INTE); + dev->resource[0].start = 0x1001000; + dev->resource[0].end = dev->resource[0].start+0xfff; + nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + dev->resource[0].start); + break; + default: + printk("\n"); + break; + } + } +} + +char *pcibios_setup (char *str) +{ + return str; +} + +struct pci_fixup pcibios_fixups[] = {}; + |