int pci_fixup_pcic(void) { ctrl_outl(0x00000001, SH7780_PCI_VCR2); /* Enable all interrupts, so we know what to fix */ pci_write_reg(0x0000C3FF, SH7780_PCIIMR); pci_write_reg(0x0000380F, SH7780_PCIAINTM); /* Set up standard PCI config registers */ ctrl_outw(0xFB00, PCI_REG(SH7780_PCISTATUS)); ctrl_outw(0x0047, PCI_REG(SH7780_PCICMD)); ctrl_outb( 0x00, PCI_REG(SH7780_PCIPIF)); ctrl_outb( 0x00, PCI_REG(SH7780_PCISUB)); ctrl_outb( 0x06, PCI_REG(SH7780_PCIBCC)); ctrl_outw(0x1912, PCI_REG(SH7780_PCISVID)); ctrl_outw(0x0001, PCI_REG(SH7780_PCISID)); pci_write_reg(0x08000000, SH7780_PCIMBAR0); /* PCI */ pci_write_reg(0x08000000, SH7780_PCILAR0); /* SHwy */ pci_write_reg(0x07F00001, SH7780_PCILSR); /* size 128M w/ MBAR */ pci_write_reg(0x00000000, SH7780_PCIMBAR1); pci_write_reg(0x00000000, SH7780_PCILAR1); pci_write_reg(0x00000000, SH7780_PCILSR1); pci_write_reg(0xAB000801, SH7780_PCIIBAR); /* * Set the MBR so PCI address is one-to-one with window, * meaning all calls go straight through... use ifdef to * catch erroneous assumption. */ pci_write_reg(0xFD000000 , SH7780_PCIMBR0); pci_write_reg(0x00FC0000 , SH7780_PCIMBMR0); /* 16M */ /* Set IOBR for window containing area specified in pci.h */ pci_write_reg(PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE-1), SH7780_PCIIOBR); pci_write_reg((SH7780_PCI_IO_SIZE-1) & (7 << 18), SH7780_PCIIOBMR); pci_write_reg(0xA5000C01, SH7780_PCICR); return 0; }
static int sh7786_pcie_config_access(unsigned char access_type, struct pci_bus *bus, unsigned int devfn, int where, u32 *data) { struct pci_channel *chan = bus->sysdata; int dev, func, type, reg; dev = PCI_SLOT(devfn); func = PCI_FUNC(devfn); type = !!bus->parent; reg = where & ~3; if (bus->number > 255 || dev > 31 || func > 7) return PCIBIOS_FUNC_NOT_SUPPORTED; /* * While each channel has its own memory-mapped extended config * space, it's generally only accessible when in endpoint mode. * When in root complex mode, the controller is unable to target * itself with either type 0 or type 1 accesses, and indeed, any * controller initiated target transfer to its own config space * result in a completer abort. * * Each channel effectively only supports a single device, but as * the same channel <-> device access works for any PCI_SLOT() * value, we cheat a bit here and bind the controller's config * space to devfn 0 in order to enable self-enumeration. In this * case the regular PAR/PDR path is sidelined and the mangled * config access itself is initiated as a SuperHyway transaction. */ if (pci_is_root_bus(bus)) { if (dev == 0) { if (access_type == PCI_ACCESS_READ) *data = pci_read_reg(chan, PCI_REG(reg)); else pci_write_reg(chan, *data, PCI_REG(reg)); return PCIBIOS_SUCCESSFUL; } else if (dev > 1) return PCIBIOS_DEVICE_NOT_FOUND; } /* Clear errors */ pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR); /* Set the PIO address */ pci_write_reg(chan, (bus->number << 24) | (dev << 19) | (func << 16) | reg, SH4A_PCIEPAR); /* Enable the configuration access */ pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR); /* Check for errors */ if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10) return PCIBIOS_DEVICE_NOT_FOUND; /* Check for master and target aborts */ if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28))) return PCIBIOS_DEVICE_NOT_FOUND; if (access_type == PCI_ACCESS_READ) *data = pci_read_reg(chan, SH4A_PCIEPDR); else pci_write_reg(chan, *data, SH4A_PCIEPDR); /* Disable the configuration access */ pci_write_reg(chan, 0, SH4A_PCIEPCTLR); return PCIBIOS_SUCCESSFUL; }
/* * Initialize the SnapGear PCI interface * Setup hardware to be Central Funtion * Copy the BSR regs to the PCI interface * Setup PCI windows into local RAM */ int __init pcibios_init_platform(void) { u32 reg; u32 word; u32 id; PCIDBG(1,"PCI: snapgear_pci_init called\n"); /* Set the BCR's to enable PCI access */ reg = inl(SH7751_BCR1); reg |= 0x80000; outl(reg, SH7751_BCR1); /* check for SH7751/SH7751R hardware */ id = inl(SH7751_PCIREG_BASE+SH7751_PCICONF0); switch (id) { case (SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID: printk("PCI: SH7751 PCI host bridge found.\n"); break; case (SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID: printk("PCI: SH7751R PCI host bridge found.\n"); break; default: printk("PCI: Unknown PCI host bridge (id=0x%x).\n", id); return(0); } /* Turn the clocks back on (not done in reset)*/ outl(0, PCI_REG(SH7751_PCICLKR)); /* Clear Powerdown IRQ's (not done in reset) */ word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0; outl(word, PCI_REG(SH7751_PCICLKR)); #if 0 /* * This code is removed as it is done in the bootloader and doing it * here means the MAC addresses loaded by the bootloader get lost */ /* toggle PCI reset pin */ word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST; outl(word,PCI_REG(SH7751_PCICR)); /* Wait for a long time... not 1 sec. but long enough */ mdelay(100); word = SH7751_PCICR_PREFIX; outl(word,PCI_REG(SH7751_PCICR)); #endif /* set the command/status bits to: * Wait Cycle Control + Parity Enable + Bus Master + * Mem space enable */ word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES; outl(word, PCI_REG(SH7751_PCICONF1)); /* define this host as the host bridge */ word = SH7751_PCI_HOST_BRIDGE << 24; outl(word, PCI_REG(SH7751_PCICONF2)); /* Set IO and Mem windows to local address * Make PCI and local address the same for easy 1 to 1 mapping * Window0 = SNAPGEAR_LSR0_SIZE @ non-cached CS2 base = SDRAM * Window1 = SNAPGEAR_LSR1_SIZE @ cached CS2 base = SDRAM */ word = SNAPGEAR_LSR0_SIZE - 1; outl(word, PCI_REG(SH7751_PCILSR0)); word = SNAPGEAR_LSR1_SIZE - 1; outl(word, PCI_REG(SH7751_PCILSR1)); /* Set the values on window 0 PCI config registers */ word = P2SEGADDR(SH7751_CS2_BASE_ADDR); outl(word, PCI_REG(SH7751_PCILAR0)); outl(word, PCI_REG(SH7751_PCICONF5)); /* Set the values on window 1 PCI config registers */ word = PHYSADDR(SH7751_CS2_BASE_ADDR); outl(word, PCI_REG(SH7751_PCILAR1)); outl(word, PCI_REG(SH7751_PCICONF6)); /* Set the local 16MB PCI memory space window to * the lowest PCI mapped address */ word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK; PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word); outl(word , PCI_REG(SH7751_PCIMBR)); /* Map IO space into PCI IO window * The IO window is 64K-PCIBIOS_MIN_IO in size * IO addresses will be translated to the * PCI IO window base address */ PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO); /* Make sure the MSB's of IO window are set to access PCI space correctly */ word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK; PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word); outl(word, PCI_REG(SH7751_PCIIOBR)); /* Set PCI WCRx, BCRx's, copy from BSC locations */ word = inl(SH7751_BCR1); /* check BCR for SDRAM in area 3 */ if(((word >> 2) & 1) == 0) { printk("PCI: Area 2 is not configured for SDRAM. BCR1=0x%x\n", word); return 0; } outl(word, PCI_REG(SH7751_PCIBCR1)); word = (u16)inw(SH7751_BCR2); /* check BCR2 for 32bit SDRAM interface*/ if(((word >> 4) & 0x3) != 0x3) { printk("PCI: Area 2 is not 32 bit SDRAM. BCR2=0x%x\n", word); return 0; } outl(word, PCI_REG(SH7751_PCIBCR2)); /* configure the wait control registers */ word = inl(SH7751_WCR1); outl(word, PCI_REG(SH7751_PCIWCR1)); word = inl(SH7751_WCR2); outl(word, PCI_REG(SH7751_PCIWCR2)); word = inl(SH7751_WCR3); outl(word, PCI_REG(SH7751_PCIWCR3)); word = inl(SH7751_MCR); outl(word, PCI_REG(SH7751_PCIMCR)); /* NOTE: I'm ignoring the PCI error IRQs for now.. * TODO: add support for the internal error interrupts and * DMA interrupts... */ /* SH7751 init done, set central function init complete */ /* use round robin mode to stop a device starving/overruning */ word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN | SH7751_PCICR_ARBM; outl(word,PCI_REG(SH7751_PCICR)); PCIDBG(2,"PCI: snapgear_pci_init finished\n"); return 1; }