/* * arch/mips/ddb5476/pci.c -- NEC DDB Vrc-5074 PCI access routines * * Copyright (C) 2000 Geert Uytterhoeven * Albert Dorofeev * Sony Software Development Center Europe (SDCE), Brussels * * $Id: pci.c,v 1.4 2000/02/18 00:02:17 ralf Exp $ */ #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; /* work around the bug for Vrc5476 */ if (slot_num == 13) return NILE4_BASE + NILE4_PCI_BASE; /* Set window 1 address 08000000 - 32 bit - 128 MB (PCI config space) */ nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x08000000, 32, 0, 0); // [jsun] we start scanning from addr:10, // with 128M we can go up to addr:26 (slot 16) if (slot_num <= 16) { virt_addr += 0x00000400 << slot_num; } else { /* for high slot, we have to set higher PCI base addr */ pci_addr = 0x00000400 << 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 08000000 - 32 bit - 128 MB (PCI IO space)*/ nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE), 0x08000000, 32, 1, 1); // nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0); nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0x08000000); } static int nile4_pci_read_config_dword( struct pci_dev *dev, int where, u32 *val) { int slot_num, func_num; u32 base; u32 addr; /* * Do we need to generate type 1 configure transaction? */ if (dev->bus->number) { /* FIXME - not working yet */ return PCIBIOS_FUNC_NOT_SUPPORTED; /* the largest type 1 configuration addr is 16M, < 256M config space */ slot_num = 0; addr = (dev->bus->number << 16) | (dev->devfn < 8) | where | 1; } else { slot_num = PCI_SLOT(dev->devfn); func_num = PCI_FUNC(dev->devfn); addr = (func_num << 8) + where; } base = nile4_pre_pci_access0(slot_num); *val = *(volatile u32 *)(base + addr); 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; u32 addr; /* * Do we need to generate type 1 configure transaction? */ if (dev->bus->number) { /* FIXME - not working yet */ return PCIBIOS_FUNC_NOT_SUPPORTED; /* the largest type 1 configuration addr is 16M, < 256M config space */ slot_num = 0; addr = (dev->bus->number << 16) | (dev->devfn < 8) | where | 1; } else { slot_num = PCI_SLOT(dev->devfn); func_num = PCI_FUNC(dev->devfn); addr = (func_num << 8) + where; } base = nile4_pre_pci_access0(slot_num); *(volatile u32 *)(base + addr) = 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 & ~3, &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 & ~3, &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 & ~3, &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 & ~3, 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 & ~3, &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 & ~3, 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 }; struct { struct resource ram; struct resource flash; struct resource isa_io; struct resource pci_io; struct resource isa_mem; struct resource pci_mem; struct resource nile4; struct resource boot; } ddb5476_resources = { // { "RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 }, { "RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM }, { "Flash ROM", 0x04000000, 0x043fffff }, { "Nile4 ISA I/O", 0x06000000, 0x060fffff }, { "Nile4 PCI I/O", 0x06100000, 0x07ffffff }, { "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM }, { "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM }, // { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 }, { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM }, { "Boot ROM", 0x1fc00000, 0x1fffffff } }; struct resource M5229_resources[5] = { { "M5229 BAR0", 0x1f0, 0x1f3, IORESOURCE_IO }, { "M5229 BAR1", 0x3f4, 0x3f7, IORESOURCE_IO }, { "M5229 BAR2", 0x170, 0x173, IORESOURCE_IO }, { "M5229 BAR3", 0x374, 0x377, IORESOURCE_IO }, { "M5229 BAR4", 0xf000, 0xf00f, IORESOURCE_IO } }; static void __init ddb5476_pci_fixup(void) { struct pci_dev *dev; pci_for_each_dev(dev) { if (dev->vendor == PCI_VENDOR_ID_NEC && dev->device == PCI_DEVICE_ID_NEC_VRC5476) { /* * The first 64-bit PCI base register should point to the Nile4 * control registers. Unfortunately this isn't the case, so we fix * it ourselves. This allows the serial driver to find the UART. */ dev->resource[0] = ddb5476_resources.nile4; request_resource(&iomem_resource, &dev->resource[0]); /* * The second 64-bit PCI base register points to the first memory * bank. Unfortunately the address is wrong, so we fix it (again). */ dev->resource[2] = ddb5476_resources.ram; request_resource(&iomem_resource, &dev->resource[2]); } else if (dev->vendor == PCI_VENDOR_ID_AL && dev->device == PCI_DEVICE_ID_AL_M7101) { /* * It's nice to have the LEDs on the GPIO pins available for * debugging */ extern struct pci_dev *pci_pmu; u8 t8; pci_pmu = dev; /* for LEDs D2 and D3 */ /* 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); } else if (dev->vendor == PCI_VENDOR_ID_AL && dev->device == 0x5229) { int i; for (i=0; i< 5; i++) { dev->resource[i] = M5229_resources[i]; request_resource(&ioport_resource, &dev->resource[i]); } } } } static void __init pcibios_fixup_irqs(void) { struct pci_dev *dev; int slot_num; pci_for_each_dev(dev) { slot_num = PCI_SLOT(dev->devfn); switch (slot_num) { case 3: /* re-programmed to USB */ dev->irq = 9; /* hard-coded; see irq.c */ break; case 4: /* re-programmed to PMU */ dev->irq = 10; /* hard-coded; see irq.c */ break; case 6: /* on-board pci-pci bridge */ dev->irq = 0xff; break; case 7: /* on-board ether */ dev->irq = nile4_to_irq(NILE4_INT_INTB); break; case 8: /* ISA-PCI bridge */ dev->irq = nile4_to_irq(NILE4_INT_INTC); break; case 9: /* ext slot #3 */ dev->irq = nile4_to_irq(NILE4_INT_INTD); break; case 10: /* ext slot #4 */ dev->irq = nile4_to_irq(NILE4_INT_INTA); break; case 13: /* Vrc5476 */ dev->irq = 0xff; break; case 14: /* HD controller, M5229 */ dev->irq = 14; break; default: printk("JSUN : in pcibios_fixup_irqs - unkown slot %d\n", slot_num); panic("JSUN : in pcibios_fixup_irqs - unkown slot.\n"); } } } void __init pcibios_init(void) { u32 base; printk("PCI: Emulate bios initialization \n"); /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */ *(long*)(NILE4_BASE + NILE4_BAR0) = 0x8; printk("PCI: Probing PCI hardware\n"); ioport_resource.end = 0x1ffffff; /* 32 MB */ iomem_resource.end = 0x1fffffff; /* 512 MB */ /* `ram' and `nile4' are requested through the Nile4 pci_dev */ request_resource(&iomem_resource, &ddb5476_resources.flash); request_resource(&iomem_resource, &ddb5476_resources.isa_io); request_resource(&iomem_resource, &ddb5476_resources.pci_io); request_resource(&iomem_resource, &ddb5476_resources.isa_mem); request_resource(&iomem_resource, &ddb5476_resources.pci_mem); request_resource(&iomem_resource, &ddb5476_resources.boot); pci_scan_bus(0, &nile4_pci_ops, NULL); ddb5476_pci_fixup(); pci_assign_unassigned_resources(); pci_set_bus_ranges(); pcibios_fixup_irqs(); } void __init pcibios_fixup_bus(struct pci_bus *bus) { /* [jsun] we don't know how to fix sub-buses yet */ if (bus->number == 0) { bus->resource[1] = &ddb5476_resources.pci_mem; } } char *pcibios_setup (char *str) { return str; } void __init pcibios_update_irq(struct pci_dev *dev, int irq) { pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges) { /* our caller figure out range by going through the dev structures. * I guess this is the place to fix things up if the bus is using a * different view of the addressing space. */ /* original DDB5074 code if (bus->number == 0) { ranges->io_start -= bus->resource[0]->start; ranges->io_end -= bus->resource[0]->start; ranges->mem_start -= bus->resource[1]->start; ranges->mem_end -= bus->resource[1]->start; } */ } int pcibios_enable_resources(struct pci_dev *dev) { u16 cmd, old_cmd; int idx; struct resource *r; /* * Don't touch the Nile 4 */ if (dev->vendor == PCI_VENDOR_ID_NEC && dev->device == PCI_DEVICE_ID_NEC_VRC5476) return 0; pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for(idx=0; idx<6; idx++) { r = &dev->resource[idx]; if (!r->start && r->end) { printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); return -EINVAL; } if (r->flags & IORESOURCE_IO) cmd |= PCI_COMMAND_IO; if (r->flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; } if (cmd != old_cmd) { printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); pci_write_config_word(dev, PCI_COMMAND, cmd); } return 0; } int pcibios_enable_device(struct pci_dev *dev) { return pcibios_enable_resources(dev); } void pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *res, int resource) { u32 new, check; int reg; new = res->start | (res->flags & PCI_REGION_FLAG_MASK); if (resource < 6) { reg = PCI_BASE_ADDRESS_0 + 4*resource; } else if (resource == PCI_ROM_RESOURCE) { res->flags |= PCI_ROM_ADDRESS_ENABLE; reg = dev->rom_base_reg; } else { /* Somebody might have asked allocation of a non-standard resource */ return; } pci_write_config_dword(dev, reg, new); pci_read_config_dword(dev, reg, &check); if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { printk(KERN_ERR "PCI: Error while updating region " "%s/%d (%08x != %08x)\n", dev->slot_name, resource, new, check); } } void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { struct pci_dev *dev = data; if (res->flags & IORESOURCE_IO) { unsigned long start = res->start; /* We need to avoid collisions with `mirrored' VGA ports and other strange ISA hardware, so we always want the addresses kilobyte aligned. */ if (size > 0x100) { printk(KERN_ERR "PCI: I/O Region %s/%d too large" " (%ld bytes)\n", dev->slot_name, dev->resource - res, size); } start = (start + 1024 - 1) & ~(1024 - 1); res->start = start; } } struct pci_fixup pcibios_fixups[] = { {0} };