/* * arch/mips/ddb5074/pci.c -- NEC DDB Vrc-5074 PCI access routines * * Copyright (C) 2000 Geert Uytterhoeven * Albert Dorofeev * Sony Suprastructure Center Europe (SUPC-E), Brussels * * $Id$ */ #include #include #include #include #include #include #include #include #include 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[] = {};