#ifdef CONFIG_SSB_PCICORE_HOSTMODE
#include <asm/paccess.h>
-/* Read the bus and catch bus exceptions. This is MIPS specific. */
-#define mips_busprobe(val, addr) get_dbe((val), (addr))
+/* Probe a 32bit value on the bus and catch bus exceptions.
+ * Returns nonzero on a bus exception.
+ * This is MIPS specific */
+#define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr)))
/* Assume one-hot slot wiring */
#define SSB_PCI_SLOT_MAX 16
/* Core to access the external PCI config space. Can only have one. */
static struct ssb_pcicore *extpci_core;
-u32 pci_iobase = 0x100;
-u32 pci_membase = SSB_PCI_DMA;
+static u32 ssb_pcicore_pcibus_iobase = 0x100;
+static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
int pcibios_plat_dev_init(struct pci_dev *d)
{
int pos, size;
u32 *base;
- printk("PCI: Fixing up device %s\n", pci_name(d));
+ ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
+ pci_name(d));
/* Fix up resource bases */
for (pos = 0; pos < 6; pos++) {
res = &d->resource[pos];
- base = ((res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase);
+ if (res->flags & IORESOURCE_IO)
+ base = &ssb_pcicore_pcibus_iobase;
+ else
+ base = &ssb_pcicore_pcibus_membase;
if (res->end) {
size = res->end - res->start + 1;
if (*base & (size - 1))
if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
return;
- printk("PCI: fixing up bridge\n");
+ ssb_printk(KERN_INFO "PCI: fixing up bridge\n");
/* Enable PCI bridge bus mastering and memory space */
pci_set_master(dev);
if (unlikely(pc->cardbusmode && dev > 1))
goto out;
- if (bus == 0) {//FIXME busnumber ok?
+ if (bus == 0) {
/* Type 0 transaction */
if (unlikely(dev >= SSB_PCI_SLOT_MAX))
goto out;
u32 addr, val;
void __iomem *mmio;
- assert(pc->hostmode);
+ SSB_WARN_ON(!pc->hostmode);
if (unlikely(len != 1 && len != 2 && len != 4))
goto out;
addr = get_cfgspace_addr(pc, bus, dev, func, off);
if (!mmio)
goto out;
- if (mips_busprobe(val, (u32 *) mmio)) {
+ if (mips_busprobe32(val, mmio)) {
val = 0xffffffff;
goto unmap;
}
u32 addr, val = 0;
void __iomem *mmio;
- assert(pc->hostmode);
+ SSB_WARN_ON(!pc->hostmode);
if (unlikely(len != 1 && len != 2 && len != 4))
goto out;
addr = get_cfgspace_addr(pc, bus, dev, func, off);
if (!mmio)
goto out;
- if (mips_busprobe(val, (u32 *) mmio)) {
+ if (mips_busprobe32(val, mmio)) {
val = 0xffffffff;
goto unmap;
}
static struct resource ssb_pcicore_mem_resource = {
.name = "SSB PCIcore external memory",
.start = SSB_PCI_DMA,
- .end = (u32)SSB_PCI_DMA + (u32)SSB_PCI_DMA_SZ - 1,
+ .end = SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1,
.flags = IORESOURCE_MEM,
};
{
u32 val;
- if (extpci_core) {
- WARN_ON(1);
+ if (WARN_ON(extpci_core))
return;
- }
extpci_core = pc;
ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n");
pcicore_write32(pc, SSB_PCICORE_CTL, val);
val |= SSB_PCICORE_CTL_CLK; /* Clock on */
pcicore_write32(pc, SSB_PCICORE_CTL, val);
- udelay(150);
+ udelay(150); /* Assertion time demanded by the PCI standard */
val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */
pcicore_write32(pc, SSB_PCICORE_CTL, val);
val = SSB_PCICORE_ARBCTL_INTERN;
- pcicore_write32(pc, SSB_PCICORE_ARBCTL, val);
- udelay(1);
+ pcicore_write32(pc, SSB_PCICORE_ARBCTL, val);
+ udelay(1); /* Assertion time demanded by the PCI standard */
- //TODO cardbus mode
+ /*TODO cardbus mode */
/* 64MB I/O window */
pcicore_write32(pc, SSB_PCICORE_SBTOPCI0,
* The following needs change, if we want to port hostmode
* to non-MIPS platform. */
set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000));
- mdelay(300);
+ /* Give some time to the PCI controller to configure itself with the new
+ * values. Not waiting at this point causes crashes of the machine. */
+ mdelay(10);
register_pci_controller(&ssb_pcicore_controller);
}
if (bus->chip_id == 0x5350)
return 0;
- return !mips_busprobe(tmp, (u32 *) (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE)));
+ return !mips_busprobe32(tmp, (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE)));
}
#endif /* CONFIG_SSB_PCICORE_HOSTMODE */
v |= (u32)address << 18;
v |= data;
pcicore_write32(pc, mdio_data, v);
+ /* Wait for the device to complete the transaction */
udelay(10);
for (i = 0; i < 10; i++) {
v = pcicore_read32(pc, mdio_control);
struct ssb_device *dev;
dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev;
- assert(dev);
+ if (WARN_ON(!dev))
+ return;
/* This forces an update of the cached registers. */
ssb_broadcast_value(dev, 0xFD8, 0);
}
u32 intvec;
intvec = ssb_read32(pdev, SSB_INTVEC);
- tmp = ssb_read32(dev, SSB_TPSFLAG);
- tmp &= SSB_TPSFLAG_BPFLAG;
- intvec |= tmp;
+ if ((bus->chip_id & 0xFF00) == 0x4400) {
+ /* Workaround: On the BCM44XX the BPFLAG routing
+ * bit is wrong. Use a hardcoded constant. */
+ intvec |= 0x00000002;
+ } else {
+ tmp = ssb_read32(dev, SSB_TPSFLAG);
+ tmp &= SSB_TPSFLAG_BPFLAG;
+ intvec |= tmp;
+ }
ssb_write32(pdev, SSB_INTVEC, intvec);
}
pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp);
}
} else {
- assert(pdev->id.coreid == SSB_DEV_PCIE);
+ WARN_ON(pdev->id.coreid != SSB_DEV_PCIE);
//TODO: Better make defines for all these magic PCIE values.
if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) {
/* TLP Workaround register. */