diff options
Diffstat (limited to 'target/linux/brcm47xx/patches-3.2/0040-bcma-add-PCIe-host-controller.patch')
| -rw-r--r-- | target/linux/brcm47xx/patches-3.2/0040-bcma-add-PCIe-host-controller.patch | 845 | 
1 files changed, 0 insertions, 845 deletions
diff --git a/target/linux/brcm47xx/patches-3.2/0040-bcma-add-PCIe-host-controller.patch b/target/linux/brcm47xx/patches-3.2/0040-bcma-add-PCIe-host-controller.patch deleted file mode 100644 index 2afd09aee..000000000 --- a/target/linux/brcm47xx/patches-3.2/0040-bcma-add-PCIe-host-controller.patch +++ /dev/null @@ -1,845 +0,0 @@ -From 47d0e8c2743729b4248585d33b55b6aaeac008d5 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 8 Jan 2012 16:53:15 +0100 -Subject: [PATCH 25/34] bcma: add PCIe host controller - -Some SoCs have a PCIe host controller to make it possible to attach -some other devices to it, like an other Wifi card. -This code was tested with an Netgear WNDR3400 (bcm4716 based), but -should work with all bcma based SoCs. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/mips/pci/pci-bcm47xx.c          |   49 +++- - drivers/bcma/bcma_private.h          |    1 + - drivers/bcma/driver_pci.c            |   38 +-- - drivers/bcma/driver_pci_host.c       |  576 +++++++++++++++++++++++++++++++++- - include/linux/bcma/bcma_driver_pci.h |   34 ++ - include/linux/bcma/bcma_regs.h       |   27 ++ - 6 files changed, 686 insertions(+), 39 deletions(-) - ---- a/arch/mips/pci/pci-bcm47xx.c -+++ b/arch/mips/pci/pci-bcm47xx.c -@@ -25,6 +25,7 @@ - #include <linux/types.h> - #include <linux/pci.h> - #include <linux/ssb/ssb.h> -+#include <linux/bcma/bcma.h> - #include <bcm47xx.h> -  - int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -@@ -32,15 +33,12 @@ int __init pcibios_map_irq(const struct - 	return 0; - } -  --int pcibios_plat_dev_init(struct pci_dev *dev) --{ - #ifdef CONFIG_BCM47XX_SSB -+static int bcm47xx_pcibios_plat_dev_init_ssb(struct pci_dev *dev) -+{ - 	int res; - 	u8 slot, pin; -  --	if (bcm47xx_bus_type !=  BCM47XX_BUS_TYPE_SSB) --		return 0; -- - 	res = ssb_pcibios_plat_dev_init(dev); - 	if (res < 0) { - 		printk(KERN_ALERT "PCI: Failed to init device %s\n", -@@ -60,6 +58,47 @@ int pcibios_plat_dev_init(struct pci_dev - 	} -  - 	dev->irq = res; -+	return 0; -+} - #endif -+ -+#ifdef CONFIG_BCM47XX_BCMA -+static int bcm47xx_pcibios_plat_dev_init_bcma(struct pci_dev *dev) -+{ -+	int res; -+ -+	res = bcma_core_pci_plat_dev_init(dev); -+	if (res < 0) { -+		printk(KERN_ALERT "PCI: Failed to init device %s\n", -+		       pci_name(dev)); -+		return res; -+	} -+ -+	res = bcma_core_pci_pcibios_map_irq(dev); -+ -+	/* IRQ-0 and IRQ-1 are software interrupts. */ -+	if (res < 2) { -+		printk(KERN_ALERT "PCI: Failed to map IRQ of device %s\n", -+		       pci_name(dev)); -+		return res; -+	} -+ -+	dev->irq = res; - 	return 0; - } -+#endif -+ -+int pcibios_plat_dev_init(struct pci_dev *dev) -+{ -+#ifdef CONFIG_BCM47XX_SSB -+	if (bcm47xx_bus_type ==  BCM47XX_BUS_TYPE_SSB) -+		return bcm47xx_pcibios_plat_dev_init_ssb(dev); -+	else -+#endif -+#ifdef CONFIG_BCM47XX_BCMA -+	if  (bcm47xx_bus_type ==  BCM47XX_BUS_TYPE_BCMA) -+		return bcm47xx_pcibios_plat_dev_init_bcma(dev); -+	else -+#endif -+		return 0; -+} ---- a/drivers/bcma/bcma_private.h -+++ b/drivers/bcma/bcma_private.h -@@ -55,6 +55,7 @@ extern void __exit bcma_host_pci_exit(vo - #endif /* CONFIG_BCMA_HOST_PCI */ -  - #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE -+bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); - void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); - #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ -  ---- a/drivers/bcma/driver_pci.c -+++ b/drivers/bcma/driver_pci.c -@@ -2,7 +2,7 @@ -  * Broadcom specific AMBA -  * PCI Core -  * -- * Copyright 2005, Broadcom Corporation -+ * Copyright 2005, 2011, Broadcom Corporation -  * Copyright 2006, 2007, Michael Buesch <m@bues.ch> -  * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> -  * -@@ -179,47 +179,19 @@ static void __devinit bcma_core_pci_clie - 	bcma_pcicore_serdes_workaround(pc); - } -  --static bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) --{ --	struct bcma_bus *bus = pc->core->bus; --	u16 chipid_top; -- --	chipid_top = (bus->chipinfo.id & 0xFF00); --	if (chipid_top != 0x4700 && --	    chipid_top != 0x5300) --		return false; -- --#ifdef CONFIG_SSB_DRIVER_PCICORE --	if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI) --		return false; --#endif /* CONFIG_SSB_DRIVER_PCICORE */ -- --#if 0 --	/* TODO: on BCMA we use address from EROM instead of magic formula */ --	u32 tmp; --	return !mips_busprobe32(tmp, (bus->mmio + --		(pc->core->core_index * BCMA_CORE_SIZE))); --#endif -- --	return true; --} -- - void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) - { - 	if (pc->setup_done) - 		return; -  --	if (bcma_core_pci_is_in_hostmode(pc)) { - #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE -+	pc->hostmode = bcma_core_pci_is_in_hostmode(pc); -+	if (pc->hostmode) - 		bcma_core_pci_hostmode_init(pc); --#else --		pr_err("Driver compiled without support for hostmode PCI\n"); - #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ --	} else { --		bcma_core_pci_clientmode_init(pc); --	} -  --	pc->setup_done = true; -+	if (!pc->hostmode) -+		bcma_core_pci_clientmode_init(pc); - } -  - int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, ---- a/drivers/bcma/driver_pci_host.c -+++ b/drivers/bcma/driver_pci_host.c -@@ -2,13 +2,587 @@ -  * Broadcom specific AMBA -  * PCI Core in hostmode -  * -+ * Copyright 2005 - 2011, Broadcom Corporation -+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch> -+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> -+ * -  * Licensed under the GNU/GPL. See COPYING for details. -  */ -  - #include "bcma_private.h" -+#include <linux/export.h> - #include <linux/bcma/bcma.h> -+#include <asm/paccess.h> -+ -+/* 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 BCMA_PCI_SLOT_MAX	16 -+#define	PCI_CONFIG_SPACE_SIZE	256 -+ -+bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) -+{ -+	struct bcma_bus *bus = pc->core->bus; -+	u16 chipid_top; -+	u32 tmp; -+ -+	chipid_top = (bus->chipinfo.id & 0xFF00); -+	if (chipid_top != 0x4700 && -+	    chipid_top != 0x5300) -+		return false; -+ -+	if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { -+		pr_info("This PCI core is disabled and not working\n"); -+		return false; -+	} -+ -+	bcma_core_enable(pc->core, 0); -+ -+	return !mips_busprobe32(tmp, pc->core->io_addr); -+} -+ -+static u32 bcma_pcie_read_config(struct bcma_drv_pci *pc, u32 address) -+{ -+	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); -+	pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); -+	return pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_DATA); -+} -+ -+static void bcma_pcie_write_config(struct bcma_drv_pci *pc, u32 address, -+				   u32 data) -+{ -+	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); -+	pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); -+	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_DATA, data); -+} -+ -+static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev, -+			     unsigned int func, unsigned int off) -+{ -+	u32 addr = 0; -+ -+	/* Issue config commands only when the data link is up (atleast -+	 * one external pcie device is present). -+	 */ -+	if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG) -+			  & BCMA_CORE_PCI_DLLP_LSREG_LINKUP)) -+		goto out; -+ -+	/* Type 0 transaction */ -+	/* Slide the PCI window to the appropriate slot */ -+	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); -+	/* Calculate the address */ -+	addr = pc->host_controller->host_cfg_addr; -+	addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT); -+	addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT); -+	addr |= (off & ~3); -+ -+out: -+	return addr; -+} -+ -+static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, -+				  unsigned int func, unsigned int off, -+				  void *buf, int len) -+{ -+	int err = -EINVAL; -+	u32 addr, val; -+	void __iomem *mmio = 0; -+ -+	WARN_ON(!pc->hostmode); -+	if (unlikely(len != 1 && len != 2 && len != 4)) -+		goto out; -+	if (dev == 0) { -+		/* we support only two functions on device 0 */ -+		if (func > 1) -+			return -EINVAL; -+ -+		/* accesses to config registers with offsets >= 256 -+		 * requires indirect access. -+		 */ -+		if (off >= PCI_CONFIG_SPACE_SIZE) { -+			addr = (func << 12); -+			addr |= (off & 0x0FFF); -+			val = bcma_pcie_read_config(pc, addr); -+		} else { -+			addr = BCMA_CORE_PCI_PCICFG0; -+			addr |= (func << 8); -+			addr |= (off & 0xfc); -+			val = pcicore_read32(pc, addr); -+		} -+	} else { -+		addr = bcma_get_cfgspace_addr(pc, dev, func, off); -+		if (unlikely(!addr)) -+			goto out; -+		err = -ENOMEM; -+		mmio = ioremap_nocache(addr, len); -+		if (!mmio) -+			goto out; -+ -+		if (mips_busprobe32(val, mmio)) { -+			val = 0xffffffff; -+			goto unmap; -+		} -+ -+		val = readl(mmio); -+	} -+	val >>= (8 * (off & 3)); -+ -+	switch (len) { -+	case 1: -+		*((u8 *)buf) = (u8)val; -+		break; -+	case 2: -+		*((u16 *)buf) = (u16)val; -+		break; -+	case 4: -+		*((u32 *)buf) = (u32)val; -+		break; -+	} -+	err = 0; -+unmap: -+	if (mmio) -+		iounmap(mmio); -+out: -+	return err; -+} -+ -+static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, -+				   unsigned int func, unsigned int off, -+				   const void *buf, int len) -+{ -+	int err = -EINVAL; -+	u32 addr = 0, val = 0; -+	void __iomem *mmio = 0; -+	u16 chipid = pc->core->bus->chipinfo.id; -+ -+	WARN_ON(!pc->hostmode); -+	if (unlikely(len != 1 && len != 2 && len != 4)) -+		goto out; -+	if (dev == 0) { -+		/* accesses to config registers with offsets >= 256 -+		 * requires indirect access. -+		 */ -+		if (off < PCI_CONFIG_SPACE_SIZE) { -+			addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; -+			addr |= (func << 8); -+			addr |= (off & 0xfc); -+			mmio = ioremap_nocache(addr, len); -+			if (!mmio) -+				goto out; -+		} -+	} else { -+		addr = bcma_get_cfgspace_addr(pc, dev, func, off); -+		if (unlikely(!addr)) -+			goto out; -+		err = -ENOMEM; -+		mmio = ioremap_nocache(addr, len); -+		if (!mmio) -+			goto out; -+ -+		if (mips_busprobe32(val, mmio)) { -+			val = 0xffffffff; -+			goto unmap; -+		} -+	} -+ -+	switch (len) { -+	case 1: -+		val = readl(mmio); -+		val &= ~(0xFF << (8 * (off & 3))); -+		val |= *((const u8 *)buf) << (8 * (off & 3)); -+		break; -+	case 2: -+		val = readl(mmio); -+		val &= ~(0xFFFF << (8 * (off & 3))); -+		val |= *((const u16 *)buf) << (8 * (off & 3)); -+		break; -+	case 4: -+		val = *((const u32 *)buf); -+		break; -+	} -+	if (dev == 0 && !addr) { -+		/* accesses to config registers with offsets >= 256 -+		 * requires indirect access. -+		 */ -+		addr = (func << 12); -+		addr |= (off & 0x0FFF); -+		bcma_pcie_write_config(pc, addr, val); -+	} else { -+		writel(val, mmio); -+ -+		if (chipid == 0x4716 || chipid == 0x4748) -+			readl(mmio); -+	} -+ -+	err = 0; -+unmap: -+	if (mmio) -+		iounmap(mmio); -+out: -+	return err; -+} -+ -+static int bcma_core_pci_hostmode_read_config(struct pci_bus *bus, -+					      unsigned int devfn, -+					      int reg, int size, u32 *val) -+{ -+	unsigned long flags; -+	int err; -+	struct bcma_drv_pci *pc; -+	struct bcma_drv_pci_host *pc_host; -+ -+	pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); -+	pc = pc_host->pdev; -+ -+	spin_lock_irqsave(&pc_host->cfgspace_lock, flags); -+	err = bcma_extpci_read_config(pc, PCI_SLOT(devfn), -+				     PCI_FUNC(devfn), reg, val, size); -+	spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); -+ -+	return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -+} -+ -+static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus, -+					       unsigned int devfn, -+					       int reg, int size, u32 val) -+{ -+	unsigned long flags; -+	int err; -+	struct bcma_drv_pci *pc; -+	struct bcma_drv_pci_host *pc_host; -+ -+	pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); -+	pc = pc_host->pdev; -+ -+	spin_lock_irqsave(&pc_host->cfgspace_lock, flags); -+	err = bcma_extpci_write_config(pc, PCI_SLOT(devfn), -+				      PCI_FUNC(devfn), reg, &val, size); -+	spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); -+ -+	return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -+} -+ -+/* return cap_offset if requested capability exists in the PCI config space */ -+static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc, -+					     unsigned int dev, -+					     unsigned int func, u8 req_cap_id, -+					     unsigned char *buf, u32 *buflen) -+{ -+	u8 cap_id; -+	u8 cap_ptr = 0; -+	u32 bufsize; -+	u8 byte_val; -+ -+	/* check for Header type 0 */ -+	bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, -+				sizeof(u8)); -+	if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) -+		return cap_ptr; -+ -+	/* check if the capability pointer field exists */ -+	bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val, -+				sizeof(u8)); -+	if (!(byte_val & PCI_STATUS_CAP_LIST)) -+		return cap_ptr; -+ -+	/* check if the capability pointer is 0x00 */ -+	bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr, -+				sizeof(u8)); -+	if (cap_ptr == 0x00) -+		return cap_ptr; -+ -+	/* loop thr'u the capability list and see if the requested capabilty -+	 * exists */ -+	bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8)); -+	while (cap_id != req_cap_id) { -+		bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr, -+					sizeof(u8)); -+		if (cap_ptr == 0x00) -+			return cap_ptr; -+		bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, -+					sizeof(u8)); -+	} -+ -+	/* found the caller requested capability */ -+	if ((buf != NULL) && (buflen != NULL)) { -+		u8 cap_data; -+ -+		bufsize = *buflen; -+		if (!bufsize) -+			return cap_ptr; -+ -+		*buflen = 0; -+ -+		/* copy the cpability data excluding cap ID and next ptr */ -+		cap_data = cap_ptr + 2; -+		if ((bufsize + cap_data)  > PCI_CONFIG_SPACE_SIZE) -+			bufsize = PCI_CONFIG_SPACE_SIZE - cap_data; -+		*buflen = bufsize; -+		while (bufsize--) { -+			bcma_extpci_read_config(pc, dev, func, cap_data, buf, -+						sizeof(u8)); -+			cap_data++; -+			buf++; -+		} -+	} -+ -+	return cap_ptr; -+} -+ -+/* If the root port is capable of returning Config Request -+ * Retry Status (CRS) Completion Status to software then -+ * enable the feature. -+ */ -+static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc) -+{ -+	u8 cap_ptr, root_ctrl, root_cap, dev; -+	u16 val16; -+	int i; -+ -+	cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL, -+					   NULL); -+	root_cap = cap_ptr + PCI_EXP_RTCAP; -+	bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16)); -+	if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) { -+		/* Enable CRS software visibility */ -+		root_ctrl = cap_ptr + PCI_EXP_RTCTL; -+		val16 = PCI_EXP_RTCTL_CRSSVE; -+		bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16, -+					sizeof(u16)); -+ -+		/* Initiate a configuration request to read the vendor id -+		 * field of the device function's config space header after -+		 * 100 ms wait time from the end of Reset. If the device is -+		 * not done with its internal initialization, it must at -+		 * least return a completion TLP, with a completion status -+		 * of "Configuration Request Retry Status (CRS)". The root -+		 * complex must complete the request to the host by returning -+		 * a read-data value of 0001h for the Vendor ID field and -+		 * all 1s for any additional bytes included in the request. -+		 * Poll using the config reads for max wait time of 1 sec or -+		 * until we receive the successful completion status. Repeat -+		 * the procedure for all the devices. -+		 */ -+		for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) { -+			for (i = 0; i < 100000; i++) { -+				bcma_extpci_read_config(pc, dev, 0, -+							PCI_VENDOR_ID, &val16, -+							sizeof(val16)); -+				if (val16 != 0x1) -+					break; -+				udelay(10); -+			} -+			if (val16 == 0x1) -+				pr_err("PCI: Broken device in slot %d\n", dev); -+		} -+	} -+} -  - void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) - { --	pr_err("No support for PCI core in hostmode yet\n"); -+	struct bcma_bus *bus = pc->core->bus; -+	struct bcma_drv_pci_host *pc_host; -+	u32 tmp; -+	u32 pci_membase_1G; -+	unsigned long io_map_base; -+ -+	pr_info("PCIEcore in host mode found\n"); -+ -+	pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); -+	if (!pc_host)  { -+		pr_err("can not allocate memory"); -+		return; -+	} -+ -+	pc->host_controller = pc_host; -+	pc_host->pci_controller.io_resource = &pc_host->io_resource; -+	pc_host->pci_controller.mem_resource = &pc_host->mem_resource; -+	pc_host->pci_controller.pci_ops = &pc_host->pci_ops; -+	pc_host->pdev = pc; -+ -+	pci_membase_1G = BCMA_SOC_PCI_DMA; -+	pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG; -+ -+	pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config; -+	pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config; -+ -+	pc_host->mem_resource.name = "BCMA PCIcore external memory", -+	pc_host->mem_resource.start = BCMA_SOC_PCI_DMA; -+	pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1; -+	pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED; -+ -+	pc_host->io_resource.name = "BCMA PCIcore external I/O", -+	pc_host->io_resource.start = 0x100; -+	pc_host->io_resource.end = 0x7FF; -+	pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; -+ -+	/* Reset RC */ -+	udelay(3000); -+	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); -+	udelay(1000); -+	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | -+			BCMA_CORE_PCI_CTL_RST_OE); -+ -+	/* 64 MB I/O access window. On 4716, use -+	 * sbtopcie0 to access the device registers. We -+	 * can't use address match 2 (1 GB window) region -+	 * as mips can't generate 64-bit address on the -+	 * backplane. -+	 */ -+	if (bus->chipinfo.id == 0x4716 || bus->chipinfo.id == 0x4748) { -+		pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; -+		pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + -+					    BCMA_SOC_PCI_MEM_SZ - 1; -+		pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, -+				BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM); -+	} else if (bus->chipinfo.id == 0x5300) { -+		tmp = BCMA_CORE_PCI_SBTOPCI_MEM; -+		tmp |= BCMA_CORE_PCI_SBTOPCI_PREF; -+		tmp |= BCMA_CORE_PCI_SBTOPCI_BURST; -+		if (pc->core->core_unit == 0) { -+			pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; -+			pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + -+						    BCMA_SOC_PCI_MEM_SZ - 1; -+			pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; -+			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, -+					tmp | BCMA_SOC_PCI_MEM); -+		} else if (pc->core->core_unit == 1) { -+			pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; -+			pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + -+						    BCMA_SOC_PCI_MEM_SZ - 1; -+			pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; -+			pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; -+			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, -+					tmp | BCMA_SOC_PCI1_MEM); -+		} -+	} else -+		pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, -+				BCMA_CORE_PCI_SBTOPCI_IO); -+ -+	/* 64 MB configuration access window */ -+	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); -+ -+	/* 1 GB memory access window */ -+	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2, -+			BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G); -+ -+ -+	/* As per PCI Express Base Spec 1.1 we need to wait for -+	 * at least 100 ms from the end of a reset (cold/warm/hot) -+	 * before issuing configuration requests to PCI Express -+	 * devices. -+	 */ -+	udelay(100000); -+ -+	bcma_core_pci_enable_crs(pc); -+ -+	/* Enable PCI bridge BAR0 memory & master access */ -+	tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; -+	bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); -+ -+	/* Enable PCI interrupts */ -+	pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA); -+ -+	/* Ok, ready to run, register it to the system. -+	 * The following needs change, if we want to port hostmode -+	 * to non-MIPS platform. */ -+	io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM, -+						     0x04000000); -+	pc_host->pci_controller.io_map_base = io_map_base; -+	set_io_port_base(pc_host->pci_controller.io_map_base); -+	/* 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(&pc_host->pci_controller); -+	return; -+} -+ -+/* Early PCI fixup for a device on the PCI-core bridge. */ -+static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev) -+{ -+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { -+		/* This is not a device on the PCI-core bridge. */ -+		return; -+	} -+	if (PCI_SLOT(dev->devfn) != 0) -+		return; -+ -+	pr_info("PCI: Fixing up bridge %s\n", pci_name(dev)); -+ -+	/* Enable PCI bridge bus mastering and memory space */ -+	pci_set_master(dev); -+	if (pcibios_enable_device(dev, ~0) < 0) { -+		pr_err("PCI: BCMA bridge enable failed\n"); -+		return; -+	} -+ -+	/* Enable PCI bridge BAR1 prefetch and burst */ -+	pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3); -+} -+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge); -+ -+/* Early PCI fixup for all PCI-cores to set the correct memory address. */ -+static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) -+{ -+	struct resource *res; -+	int pos; -+ -+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { -+		/* This is not a device on the PCI-core bridge. */ -+		return; -+	} -+	if (PCI_SLOT(dev->devfn) == 0) -+		return; -+ -+	pr_info("PCI: Fixing up addresses %s\n", pci_name(dev)); -+ -+	for (pos = 0; pos < 6; pos++) { -+		res = &dev->resource[pos]; -+		if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) -+			pci_assign_resource(dev, pos); -+	} -+} -+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); -+ -+/* This function is called when doing a pci_enable_device(). -+ * We must first check if the device is a device on the PCI-core bridge. */ -+int bcma_core_pci_plat_dev_init(struct pci_dev *dev) -+{ -+	struct bcma_drv_pci_host *pc_host; -+ -+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { -+		/* This is not a device on the PCI-core bridge. */ -+		return -ENODEV; -+	} -+	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, -+			       pci_ops); -+ -+	pr_info("PCI: Fixing up device %s\n", pci_name(dev)); -+ -+	/* Fix up interrupt lines */ -+	dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2; -+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); -+ -+	return 0; -+} -+EXPORT_SYMBOL(bcma_core_pci_plat_dev_init); -+ -+/* PCI device IRQ mapping. */ -+int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev) -+{ -+	struct bcma_drv_pci_host *pc_host; -+ -+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { -+		/* This is not a device on the PCI-core bridge. */ -+		return -ENODEV; -+	} -+ -+	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, -+			       pci_ops); -+	return bcma_core_mips_irq(pc_host->pdev->core) + 2; - } -+EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); ---- a/include/linux/bcma/bcma_driver_pci.h -+++ b/include/linux/bcma/bcma_driver_pci.h -@@ -160,9 +160,40 @@ struct pci_dev; - /* PCIcore specific boardflags */ - #define BCMA_CORE_PCI_BFL_NOPCI			0x00000400 /* Board leaves PCI floating */ -  -+/* PCIE Config space accessing MACROS */ -+#define BCMA_CORE_PCI_CFG_BUS_SHIFT		24	/* Bus shift */ -+#define BCMA_CORE_PCI_CFG_SLOT_SHIFT		19	/* Slot/Device shift */ -+#define BCMA_CORE_PCI_CFG_FUN_SHIFT		16	/* Function shift */ -+#define BCMA_CORE_PCI_CFG_OFF_SHIFT		0	/* Register shift */ -+ -+#define BCMA_CORE_PCI_CFG_BUS_MASK		0xff	/* Bus mask */ -+#define BCMA_CORE_PCI_CFG_SLOT_MASK		0x1f	/* Slot/Device mask */ -+#define BCMA_CORE_PCI_CFG_FUN_MASK		7	/* Function mask */ -+#define BCMA_CORE_PCI_CFG_OFF_MASK		0xfff	/* Register mask */ -+ -+/* PCIE Root Capability Register bits (Host mode only) */ -+#define BCMA_CORE_PCI_RC_CRS_VISIBILITY		0x0001 -+ -+struct bcma_drv_pci; -+ -+struct bcma_drv_pci_host { -+	struct bcma_drv_pci *pdev; -+ -+	u32 host_cfg_addr; -+	spinlock_t cfgspace_lock; -+ -+	struct pci_controller pci_controller; -+	struct pci_ops pci_ops; -+	struct resource mem_resource; -+	struct resource io_resource; -+}; -+ - struct bcma_drv_pci { - 	struct bcma_device *core; - 	u8 setup_done:1; -+	u8 hostmode:1; -+ -+	struct bcma_drv_pci_host *host_controller; - }; -  - /* Register access */ -@@ -173,4 +204,7 @@ extern void __devinit bcma_core_pci_init - extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, - 				 struct bcma_device *core, bool enable); -  -+extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev); -+extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev); -+ - #endif /* LINUX_BCMA_DRIVER_PCI_H_ */ ---- a/include/linux/bcma/bcma_regs.h -+++ b/include/linux/bcma/bcma_regs.h -@@ -56,4 +56,31 @@ - #define  BCMA_PCI_GPIO_XTAL		0x40	/* PCI config space GPIO 14 for Xtal powerup */ - #define  BCMA_PCI_GPIO_PLL		0x80	/* PCI config space GPIO 15 for PLL powerdown */ -  -+/* SiliconBackplane Address Map. -+ * All regions may not exist on all chips. -+ */ -+#define BCMA_SOC_SDRAM_BASE		0x00000000U	/* Physical SDRAM */ -+#define BCMA_SOC_PCI_MEM		0x08000000U	/* Host Mode sb2pcitranslation0 (64 MB) */ -+#define BCMA_SOC_PCI_MEM_SZ		(64 * 1024 * 1024) -+#define BCMA_SOC_PCI_CFG		0x0c000000U	/* Host Mode sb2pcitranslation1 (64 MB) */ -+#define BCMA_SOC_SDRAM_SWAPPED		0x10000000U	/* Byteswapped Physical SDRAM */ -+#define BCMA_SOC_SDRAM_R2		0x80000000U	/* Region 2 for sdram (512 MB) */ -+ -+ -+#define BCMA_SOC_PCI_DMA		0x40000000U	/* Client Mode sb2pcitranslation2 (1 GB) */ -+#define BCMA_SOC_PCI_DMA2		0x80000000U	/* Client Mode sb2pcitranslation2 (1 GB) */ -+#define BCMA_SOC_PCI_DMA_SZ		0x40000000U	/* Client Mode sb2pcitranslation2 size in bytes */ -+#define BCMA_SOC_PCIE_DMA_L32		0x00000000U	/* PCIE Client Mode sb2pcitranslation2 -+							 * (2 ZettaBytes), low 32 bits -+							 */ -+#define BCMA_SOC_PCIE_DMA_H32		0x80000000U	/* PCIE Client Mode sb2pcitranslation2 -+							 * (2 ZettaBytes), high 32 bits -+							 */ -+ -+#define BCMA_SOC_PCI1_MEM		0x40000000U	/* Host Mode sb2pcitranslation0 (64 MB) */ -+#define BCMA_SOC_PCI1_CFG		0x44000000U	/* Host Mode sb2pcitranslation1 (64 MB) */ -+#define BCMA_SOC_PCIE1_DMA_H32		0xc0000000U	/* PCIE Client Mode sb2pcitranslation2 -+							 * (2 ZettaBytes), high 32 bits -+							 */ -+ - #endif /* LINUX_BCMA_REGS_H_ */  | 
