linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] Add PCI support for ARM RealView boards
@ 2010-10-20 13:02 Colin Tuckley
  2010-10-20 13:02 ` [PATCH 1/6] Realview PCIX support - add main support module code Colin Tuckley
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: Colin Tuckley @ 2010-10-20 13:02 UTC (permalink / raw)
  To: linux-arm-kernel

The following series implements the PCI support for the
ARM RealView NEC custom Northbridge based reference boards
(PBA8, PB11MPCore and PBX).

The boards have a PCIX root complex connected to PCI and
PCIe bridges. Each board has 2 PCI slots and 2 PCIe slots.

---

Colin Tuckley (6):
      ARM Realview PCIX build file changes
      ARM Realview PCIX board file changes
      ARM Realview PCIX IRQ include file changes
      ARM Realview PCIX map include file changes
      ARM: enable bridges in pci_common_init.
      Realview PCIX support - add main support module code


 arch/arm/Kconfig                                   |    6 
 arch/arm/kernel/bios32.c                           |    5 
 arch/arm/mach-realview/Makefile                    |    6 
 arch/arm/mach-realview/include/mach/board-pb11mp.h |   11 
 arch/arm/mach-realview/include/mach/board-pba8.h   |   11 
 arch/arm/mach-realview/include/mach/board-pbx.h    |   11 
 arch/arm/mach-realview/include/mach/hardware.h     |   53 ++
 arch/arm/mach-realview/include/mach/io.h           |   18 +
 arch/arm/mach-realview/include/mach/irqs-pb11mp.h  |   11 
 arch/arm/mach-realview/include/mach/irqs-pba8.h    |    7 
 arch/arm/mach-realview/include/mach/irqs-pbx.h     |    7 
 arch/arm/mach-realview/include/mach/platform.h     |   15 -
 arch/arm/mach-realview/pcix.c                      |  538 ++++++++++++++++++++
 arch/arm/mach-realview/realview_pb11mp.c           |   18 +
 arch/arm/mach-realview/realview_pba8.c             |   16 -
 arch/arm/mach-realview/realview_pbx.c              |   14 -
 16 files changed, 692 insertions(+), 55 deletions(-)
 create mode 100755 arch/arm/mach-realview/pcix.c

-- 
Colin Tuckley

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/6] Realview PCIX support - add main support module code
  2010-10-20 13:02 [PATCH 0/6] Add PCI support for ARM RealView boards Colin Tuckley
@ 2010-10-20 13:02 ` Colin Tuckley
  2010-10-20 21:16   ` Arnd Bergmann
  2010-10-28 14:02   ` Russell King - ARM Linux
  2010-10-20 13:02 ` [PATCH 2/6] ARM: enable bridges in pci_common_init Colin Tuckley
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 15+ messages in thread
From: Colin Tuckley @ 2010-10-20 13:02 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds pcix.c - the main pci sub-system code for
the RealView boards which have PCI and PCIe interfaces
via a custom NEC northbridge chip and two bridges.

Signed-off-by: Colin Tuckley <colin.tuckley@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---

 arch/arm/mach-realview/pcix.c |  538 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 538 insertions(+), 0 deletions(-)
 create mode 100755 arch/arm/mach-realview/pcix.c

diff --git a/arch/arm/mach-realview/pcix.c b/arch/arm/mach-realview/pcix.c
new file mode 100755
index 0000000..1318403
--- /dev/null
+++ b/arch/arm/mach-realview/pcix.c
@@ -0,0 +1,538 @@
+/*
+ * Realview PCIX Support
+ *
+ * Copyright (C) 2007-2010 ARM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <mach/platform.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+
+#define PCIX_READ_ACCESS		0x06000000
+#define PCIX_WRITE_ACCESS		0x07000000
+
+/* PCI-X Configuration registers */
+#define PCI_VENID			0x00
+#define PCI_DEVID			0x02
+#define PCI_COMMAND			0x04
+#define PCI_STATUS			0x06
+#define PCI_REVID			0x08
+#define PCI_CLCODE			0x09
+#define PCI_CALISIZE			0x0C
+#define PCI_LTTIMER			0x0D
+#define PCI_HDTYPE			0x0E
+#define PCI_PTBADDR0L			0x10
+#define PCI_PTBADDR0M			0x14
+#define PCI_PTBADDR1L			0x18
+#define PCI_PTBADDR1M			0x1C
+#define PCI_PCIIOLMT			0x1D
+#define PCI_PCISSR			0x1E
+#define PCI_PCIMBAR			0x20
+#define PCI_PCIMLMT			0x22
+#define PCI_PCIPMBAR			0x24
+#define PCI_PCIPMLMT			0x26
+#define PCI_PCIPMBARU32			0x28
+#define PCI_SUBSYSVENID			0x2C
+#define PCI_PCIPMLMTU32			0x2C
+#define PCI_SUBSYSID			0x2E
+#define PCI_CAPPOINT			0x34
+#define PCI_INTLINE			0x3C
+#define PCI_INTPIN			0x3D
+#define PCI_BCNTRL			0x3E
+#define PCI_CFGADDR			0x40
+#define PCI_CFGDATA			0x44
+#define PCI_CFGATTR			0x48
+#define PCI_PINTACNT			0x50
+#define PCI_PINTXSTAT			0x54
+#define PCI_PINTXMASK			0x58
+#define PCI_SERRSTAT			0x5C
+#define PCI_PERRADDRL			0x60
+#define PCI_PERRADDRH			0x64
+#define PCI_PERRSTAT			0x68
+#define PCI_PERRMASK			0x6C
+#define PCI_OCBERRSTAT			0x78
+#define PCI_OCBERRMASK			0x7C
+#define PCI_MSICAPID			0x80
+#define PCI_MSINXTCAP			0x81
+#define PCI_MSGCNT			0x82
+#define PCI_MSGADDR			0x84
+#define PCI_MSGUPADDR			0x88
+#define PCI_MSGDATA			0x8C
+#define PCI_PCIXCAPID			0x90
+#define PCI_PCIXNXTCAP			0x91
+#define PCI_PCIXCOMMAND			0x92
+#define PCI_PCIXSTAT			0x94
+#define PCI_SPCMPERRMSG			0x98
+#define PCI_PTMEMSEG0			0xA0
+#define PCI_PTMEMMSK0			0xA4
+#define PCI_PTMEMENSW0			0xA8
+#define PCI_PTMEMSEG1			0xB0
+#define PCI_PTMEMMSK1			0xB4
+#define PCI_PTMEMENSW1			0xB8
+#define PCI_PMSEGL			0xC0
+#define PCI_PMSEGH			0xC4
+#define PCI_DRSTCNT			0xEC
+#define PCI_PRST			0xF0
+#define PCI_UNITCNT			0xF4
+#define PCI_CNTOTIMER			0xF8
+#define PCI_PSLADAFLASH			0xFC
+
+static int irq_gic_start;
+
+/*
+ * Software is exposed to downstream half of the PCI-X bridge registers
+ * rather than a real PCI interface. Therefore there's no config memory
+ * region as such.
+ *
+ *	PCI Regions:
+ *	MEM		0xA0000000 - 0xBFFFFFFF
+ *	IO		0x00000000 - 0x0000FFFF
+ *	CONFIG		-
+ */
+
+static void realview_pb_pcix_sync(void)
+{
+	readl(PCIX_UNIT_BASE + PCI_VENID);
+}
+
+static void realview_pb_pcix_unit_init(void)
+{
+	u32 data = readl(PCIX_UNIT_BASE + PCI_UNITCNT);
+
+	if (data & 0x10)
+		writel(0x00000000, PCIX_UNIT_BASE + PCI_PRST); /* Assert PCI reset */
+	else {
+		printk(KERN_ERR "Error: PCI-X unit not in PCI-X mode.\n");
+		writel(data | 0x80000000, PCIX_UNIT_BASE + PCI_UNITCNT);
+	}
+
+	writew(0x0006, PCIX_UNIT_BASE + PCI_COMMAND); /* Master-Memory enable */
+	writew(0xfb30, PCIX_UNIT_BASE + PCI_STATUS);  /* Error bit clear */
+
+	writeb(0x08, PCIX_UNIT_BASE + PCI_CALISIZE); /* Cache line size */
+	writeb(0x40, PCIX_UNIT_BASE + PCI_LTTIMER);  /* Latency Timer */
+
+	/* Master Segment Address[31:24] */
+	writel(0x00000003, PCIX_UNIT_BASE + PCI_PMSEGL); /* no swap */
+	/* Master Segment Address[63:32] */
+	writel(0x00000000, PCIX_UNIT_BASE + PCI_PMSEGH);
+
+	/* Data endian swap mode */
+	writel(0x00000003, PCIX_UNIT_BASE + PCI_PTMEMENSW0); /* no swap */
+	writel(0x00000003, PCIX_UNIT_BASE + PCI_PTMEMENSW1); /* no swap */
+
+#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
+	/* 512MB of DMA capable RAM is available - mapped at 0x70000000
+	 * Note :- 0x70000000 is *not* on a 512MB boundary so it
+	 * must be mapped in two parts */
+	/* Window#0 256MB and enable */
+	writel(0x0fff0001, PCIX_UNIT_BASE + PCI_PTMEMMSK0);
+	/* Window#1 256MB and enable */
+	writel(0x0fff0001, PCIX_UNIT_BASE + PCI_PTMEMMSK1);
+
+	/* Window base address setting */
+	/* Memory Base Address, Ptrefetch Disable, 64bit */
+	writel(0x70000004, PCIX_UNIT_BASE + PCI_PTBADDR0L);
+	/* Memory Base Address[63:32] */
+	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR0M);
+
+	/* Memory Base Address, Ptrefetch Disable, 64bit */
+	writel(0x80000004, PCIX_UNIT_BASE + PCI_PTBADDR1L);
+	/* Memory Base Address[63:32] */
+	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR1M);
+#else
+	/* Only 256MB of RAM is available - mapped at zero */
+	/* Window#0 256MB and enable */
+	writel(0x0fff0001, PCIX_UNIT_BASE + PCI_PTMEMMSK0);
+	/* Window#1 Disable */
+	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTMEMMSK1);
+
+	/* Window base address setting */
+	/* Memory Base Address, Ptrefetch Disable, 64bit */
+	writel(0x00000004, PCIX_UNIT_BASE + PCI_PTBADDR0L);
+	/* Memory Base Address[63:32] */
+	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR0M);
+
+	/* Memory Base Address, Ptrefetch Disable, 64bit */
+	writel(0x00000004, PCIX_UNIT_BASE + PCI_PTBADDR1L);
+	/* Memory Base Address[63:32] */
+	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR1M);
+#endif
+
+	/* OnChipBus Address#0[35:24] */
+	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTMEMSEG0);
+	/* OnChipBus Address#1[35:24] */
+	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTMEMSEG1);
+
+	/* 66MHz, 64bit device */
+	writel(0x00010000, PCIX_UNIT_BASE + PCI_PCIXSTAT);
+	/* Interrupt Mask */
+	writel(0x00000000, PCIX_UNIT_BASE + PCI_PINTXMASK);
+	/* Enable PCI error status */
+	writel(0x000307f7, PCIX_UNIT_BASE + PCI_PERRMASK);
+	/* Clear PCI error status */
+	writel(0x000307f7, PCIX_UNIT_BASE + PCI_PERRSTAT);
+	/* Enable count out */
+	writel(0x10FFFFFF, PCIX_UNIT_BASE + PCI_CNTOTIMER);
+
+	realview_pb_pcix_sync();
+	udelay(1500); /* Allow hardware to settle */
+
+	/* Deassert PCI reset */
+	writel(0x00000001, PCIX_UNIT_BASE + PCI_PRST);
+	/* Initial end, Enable arbiter */
+	writel(data | 0x80000020, PCIX_UNIT_BASE + PCI_UNITCNT);
+	realview_pb_pcix_sync();
+	udelay(1500); /* Allow hardware to settle */
+
+	/* Enable bursts on PCI-X */
+	writel(0x1, __io_address(REALVIEW_ISSP_REG_BASE + 0x18));
+}
+
+void realview_pb_pcix_set_attr(unsigned int tag)
+{
+	/* Get Device and Funcion number */
+	u32 data = readl(PCIX_UNIT_BASE + PCI_PCIXSTAT) & 0x0ff;
+	/* attribute set */
+	writel(tag | (data << 8), PCIX_UNIT_BASE + PCI_CFGATTR);
+}
+
+int realview_pb_pcix_set_config(u32 bus, u32 dev, u32 func, int offset)
+{
+	u32 mode;
+	u32 config_addr;
+
+	writel(0x000307F7, PCIX_UNIT_BASE + PCI_PERRSTAT); /* clear error bit */
+	writew(0xfb30, PCIX_UNIT_BASE + PCI_STATUS);	   /* error bit clear */
+
+	if (bus == 0) {
+		/* Type0 Configuration cycle */
+		mode = readl(PCIX_UNIT_BASE + PCI_UNITCNT);
+		if (mode & 0x1) {
+			/* check PCI mode */
+			printk(KERN_ERR "PCI mode detected during config cycle"
+			       "attempt. Should really be in PCI-X mode.\n");
+			BUG();
+		} else {
+			/* PCI-X Mode
+			 *
+			 * Note that the root complex appears as id 0x1f
+			 * since we don't want to allocate this as a device
+			 * we stop scanning before we find it.
+			 */
+			if (dev < 0x10 || dev > 0x1e) {
+				realview_pb_pcix_sync();
+				return -1;
+			}
+			config_addr = (1 << dev) | ((dev & 0x1f) << 11) |
+				      ((func & 0x7) << 8) | (offset & 0xfc);
+			writel(config_addr, PCIX_UNIT_BASE + PCI_CFGADDR);
+		}
+	} else {
+		config_addr = ((bus & 0xff) << 16) | ((dev & 0x1f) << 11) |
+			      ((func & 0x7) << 8) | (offset & 0xfc) | 0x1;
+		/* Type1 Configuration cycle */
+		writel(config_addr, PCIX_UNIT_BASE + PCI_CFGADDR);
+	}
+	realview_pb_pcix_sync();
+	return 0;
+}
+
+int realview_pb_pcix_check_error(void)
+{
+	u32 data;
+	realview_pb_pcix_sync();
+	data = readl(PCIX_UNIT_BASE + PCI_PERRSTAT);
+	if (data) {
+		writel(data, PCIX_UNIT_BASE + PCI_PERRSTAT);
+		return data;
+	}
+	return 0;
+}
+
+int realview_pb_pci_read_config(struct pci_bus *pbus, u32 devfn,
+				     int offset, int size, u32 *data)
+{
+	u32 bus = pbus->number;
+	u32 slot = PCI_SLOT(devfn);
+	u32 function = PCI_FUNC(devfn);
+
+	realview_pb_pcix_set_attr(PCIX_READ_ACCESS);
+	if (realview_pb_pcix_set_config(bus, slot, function, offset) != 0) {
+		*data = ((size == 1) ? 0xFF : ((size == 2) ? 0xFFFF : 0xFFFFFFFF));
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	switch (size) {
+	case 1:
+		*data = (readl(PCIX_UNIT_BASE + PCI_CFGDATA) >>
+			 (8 * (offset & 3))) & 0xff;
+		break;
+	case 2:
+		*data = (u32)readw(PCIX_UNIT_BASE + PCI_CFGDATA +
+				   (offset & 3));
+		break;
+	default:
+		*data = readl(PCIX_UNIT_BASE + PCI_CFGDATA);
+	}
+	/* Error codes from downstream bus don't mean much for software. */
+	if (!realview_pb_pcix_check_error())
+		return PCIBIOS_SUCCESSFUL;
+
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+int realview_pb_pci_write_config(struct pci_bus *pbus, u32 devfn,
+				      int offset, int size, u32 data)
+{
+	u32 slot = PCI_SLOT(devfn);
+	u32 function = PCI_FUNC(devfn);
+	u32 bus = pbus->number;
+	int err;
+
+	realview_pb_pcix_set_attr(PCIX_WRITE_ACCESS);
+	if (realview_pb_pcix_set_config(bus, slot, function, offset) != 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (size) {
+	case 1:
+		writeb(data, PCIX_UNIT_BASE + PCI_CFGDATA + (offset & 3));
+		break;
+	case 2:
+		writew(data, PCIX_UNIT_BASE + PCI_CFGDATA + (offset & 3));
+		break;
+	default:
+		writel(data, PCIX_UNIT_BASE + PCI_CFGDATA);
+		break;
+	}
+	/* Write errors don't really matter */
+	err = realview_pb_pcix_check_error();
+	realview_pb_pcix_set_attr(PCIX_READ_ACCESS);
+	return err;
+}
+
+static struct pci_ops pci_realview_pb_ops = {
+	.read	= realview_pb_pci_read_config,
+	.write	= realview_pb_pci_write_config,
+};
+
+static int __init pci_realview_pb_setup(int nr, struct pci_sys_data *sys)
+{
+	if (machine_is_realview_pb11mp())
+		irq_gic_start = IRQ_PB11MP_GIC_START;
+	else
+		irq_gic_start = IRQ_PBA8_GIC_START;
+
+	realview_pb_pcix_unit_init();
+
+	/* set bus->cpu mapping */
+	sys->mem_offset = 0;
+	sys->io_offset = REALVIEW_PB_PCI_IO_BASE;
+
+	/* Note: we don't reserve the addresses for PCI space here because the
+	 * window allocator won't be able to get any if we do.
+	 */
+
+	return 1;
+}
+
+
+static struct pci_bus *pci_realview_pb_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &pci_realview_pb_ops, sys);
+}
+
+static void __init pci_realview_pb_preinit(void)
+{
+	u32 data = readl(__io_address(REALVIEW_SYS_PCI_STAT));
+	data &= ~0x00000100; /* Clear the Clock Control bit */
+	writel(data, __io_address(REALVIEW_SYS_PCI_STAT));
+	udelay(1500); /* Allow hardware to settle */
+}
+
+static struct pci_dev *pcie_bridge;
+
+/* Maps scrambled IRQ pins to IRQ lines. Scrambling depends on device slot. */
+static int __init pci_realview_pb_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+	int devslot = PCI_SLOT(dev->devfn);
+
+	/* Upstream port of 8518 device */
+	if (unlikely(dev->device == 0x8518 && dev->bus->primary == 0)) {
+		BUG_ON(pcie_bridge);	/* Can't be already assigned */
+		pcie_bridge = dev;
+	}
+
+	if (pcie_bridge) {
+		if (dev->bus->primary >= pcie_bridge->bus->secondary &&
+		    dev->bus->primary <= pcie_bridge->bus->subordinate) {
+			/*
+			 * The problem is that in PCIE in different slots a device
+			 * could still get the same slot/pin/devslot triplet. Therefore
+			 * we check the slot/pin/devslot triplet of an underlying PCIE port.
+			 *
+			 * slot   pin	 irq
+			 * 0	  #A(1)  56
+			 * 0	  #B(2)  57
+			 * 0	  #C(3)  54
+			 * 0	  #D(4)  55
+			 * 1	  #A(1)  55
+			 * 1	  #B(2)  56
+			 * 1	  #C(3)  57
+			 * 1	  #D(4)  54
+			 * 2	  1	 54
+			 * 2	  2	 55
+			 * 2	  3	 56
+			 * 2	  4	 57
+			 * 3	  1	 57
+			 * 3	  2	 54
+			 * 3	  3	 55
+			 * 3	  4	 56
+			 * 4	  1	 56
+			 * 4	  2	 57
+			 * 4	  3	 54
+			 * 4	  4	 55
+			 */
+
+			if (dev->bus->self) {
+				/* We do have a bus above us
+				 * Device is right behind a PCIE hub port, and its not a PCIE
+				 * hub port itself. */
+				if (dev->bus->self->device == 0x8518 &&
+				    dev->device != 0x8518) {
+					/* Depend on devslot of 8518 port we're connected to */
+					devslot = PCI_SLOT(dev->bus->self->devfn);
+					/* These are the two cases for PCIE ports on PB boards.
+					 * Any other downstream bus topology (e.g. with further
+					 * PCIE bridges) does not scramble, and get the same
+					 * irq number as the upstream bus. */
+					irq = irq_gic_start + 54 + ((devslot & 3) + (pin - 1)) % 4;
+				} else if ((dev->bus->self->class & 0xff0000) == 0x060000 &&
+					   (dev->class & 0xff0000) != 0x060000) {
+					/* It's a device behind a bridge that isn't an 8518 */
+					irq = irq_gic_start + 54 + ((devslot & 3) + pin +
+					      PCI_SLOT(dev->bus->self->bus->self->devfn) - 1) % 4;
+				} else {
+					/* It's another bridge */
+					irq = dev->bus->self->irq;
+				}
+			} else
+				irq = 0;
+
+			printk(KERN_INFO "PCI Express irq mapping: device: 0x%x, slot %d, pin %d, devslot %d, irq: %d\n",
+			       dev->device, slot, pin, devslot, irq);
+
+			return irq;
+		}
+	}
+
+	/*
+	 * slot	  pin	 irq
+	 * 0	  #A(3)  53
+	 * 0	  #B(0)  50
+	 * 0	  #C(1)  51
+	 * 0	  #D(2)  52
+	 *
+	 * 1	  #A(2)  52
+	 * 1	  #B(3)  53
+	 * 1	  #C(0)  50
+	 * 1	  #D(1)  51
+	 *
+	 * 2	  1	 51
+	 * 2	  2	 52
+	 * 2	  3	 53
+	 * 2	  0	 50
+	 *
+	 * 3	  0	 50
+	 * 3	  1	 51
+	 * 3	  2	 52
+	 * 3	  3	 53
+	 *
+	 * Note: pin is actually 1..4 not 0..3
+	 */
+
+	irq = irq_gic_start + 50 + (((pin - 1) + 3 - (devslot & 3)) & 3);
+
+	printk(KERN_INFO "PCI map irq: slot %d, pin %d, devslot %d, irq: %d\n",
+	       slot, pin, devslot, irq);
+
+	return irq;
+
+}
+
+static struct hw_pci realview_pb_pci __initdata = {
+	.swizzle		= NULL,
+	.map_irq		= pci_realview_pb_map_irq,
+	.nr_controllers		= 1,
+	.setup			= pci_realview_pb_setup,
+	.scan			= pci_realview_pb_scan_bus,
+	.preinit		= pci_realview_pb_preinit
+};
+
+static int __init realview_pb_pci_init(void)
+{
+	if (machine_is_realview_pb11mp() ||
+	    machine_is_realview_pba8() || machine_is_realview_pbx())
+		pci_common_init(&realview_pb_pci);
+	return 0;
+}
+
+subsys_initcall(realview_pb_pci_init);
+
+
+static void pcie_fix_sizes(void)
+{
+	struct pci_dev *pdev = NULL;
+	int rrq;
+	int max_rrq = 4096;
+
+	/* Set the max read request size for all devices to the
+	 * smallest in the tree. So far, the only device we've seen
+	 * that fails without this is the Marvell Yukon 88E8053 but
+	 * this may fix other devices too.
+	 */
+	while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
+		rrq = pcie_get_readrq(pdev);
+		if (rrq > 0 && rrq < max_rrq)
+			max_rrq = rrq;
+	}
+
+	pdev = NULL;	/* reset scan */
+	while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
+		rrq = pcie_get_readrq(pdev);
+		printk(KERN_DEBUG "%s: %02x:%02x %04x/%04x : RRQSZ %d -> %d\n",
+				__func__, pdev->bus->number, pdev->devfn,
+				pdev->vendor, pdev->device, rrq, max_rrq);
+		pcie_set_readrq(pdev, max_rrq);
+	}
+}
+
+static int __init realview_pcie_fixups(void)
+{
+	pcie_fix_sizes();
+	return 0;
+}
+late_initcall(realview_pcie_fixups);

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/6] ARM: enable bridges in pci_common_init.
  2010-10-20 13:02 [PATCH 0/6] Add PCI support for ARM RealView boards Colin Tuckley
  2010-10-20 13:02 ` [PATCH 1/6] Realview PCIX support - add main support module code Colin Tuckley
@ 2010-10-20 13:02 ` Colin Tuckley
  2010-10-20 13:03 ` [PATCH 3/6] ARM Realview PCIX map include file changes Colin Tuckley
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: Colin Tuckley @ 2010-10-20 13:02 UTC (permalink / raw)
  To: linux-arm-kernel

Add a missing call to pci_enable_bridges() so that devices behind
bridges get found by the pci bus scan.

Signed-off-by: Chris Partington <chris.partington@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---

 arch/arm/kernel/bios32.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index c6273a3..d86fcd4 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -583,6 +583,11 @@ void __init pci_common_init(struct hw_pci *hw)
 			 * Assign resources.
 			 */
 			pci_bus_assign_resources(bus);
+
+			/*
+			 * Enable bridges
+			 */
+			pci_enable_bridges(bus);
 		}
 
 		/*

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/6] ARM Realview PCIX map include file changes
  2010-10-20 13:02 [PATCH 0/6] Add PCI support for ARM RealView boards Colin Tuckley
  2010-10-20 13:02 ` [PATCH 1/6] Realview PCIX support - add main support module code Colin Tuckley
  2010-10-20 13:02 ` [PATCH 2/6] ARM: enable bridges in pci_common_init Colin Tuckley
@ 2010-10-20 13:03 ` Colin Tuckley
  2010-10-20 21:28   ` Arnd Bergmann
  2010-10-20 13:03 ` [PATCH 4/6] ARM Realview PCIX IRQ " Colin Tuckley
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Colin Tuckley @ 2010-10-20 13:03 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the memory map PCI support to the include
files for the Realview Northbridge based boards.

Signed-off-by: Colin Tuckley <colin.tuckley@arm.com>
---

 arch/arm/mach-realview/include/mach/board-pb11mp.h |   11 ----
 arch/arm/mach-realview/include/mach/board-pba8.h   |   11 ----
 arch/arm/mach-realview/include/mach/board-pbx.h    |   11 ----
 arch/arm/mach-realview/include/mach/hardware.h     |   53 ++++++++++++++++++++
 arch/arm/mach-realview/include/mach/io.h           |   18 ++++++-
 arch/arm/mach-realview/include/mach/platform.h     |   15 +-----
 6 files changed, 72 insertions(+), 47 deletions(-)

diff --git a/arch/arm/mach-realview/include/mach/board-pb11mp.h b/arch/arm/mach-realview/include/mach/board-pb11mp.h
index 7abf918..0114edb 100644
--- a/arch/arm/mach-realview/include/mach/board-pb11mp.h
+++ b/arch/arm/mach-realview/include/mach/board-pb11mp.h
@@ -62,17 +62,6 @@
 #define REALVIEW_PB11MP_SYS_PLD_CTRL1		0x74
 
 /*
- * PB11MPCore PCI regions
- */
-#define REALVIEW_PB11MP_PCI_BASE		0x90040000	/* PCI-X Unit base */
-#define REALVIEW_PB11MP_PCI_IO_BASE		0x90050000	/* IO Region on AHB */
-#define REALVIEW_PB11MP_PCI_MEM_BASE		0xA0000000	/* MEM Region on AHB */
-
-#define REALVIEW_PB11MP_PCI_BASE_SIZE		0x10000		/* 16 Kb */
-#define REALVIEW_PB11MP_PCI_IO_SIZE		0x1000		/* 4 Kb */
-#define REALVIEW_PB11MP_PCI_MEM_SIZE		0x20000000	/* 512 MB */
-
-/*
  * Testchip peripheral and fpga gic regions
  */
 #define REALVIEW_TC11MP_SCU_BASE		0x1F000000	/* IRQ, Test chip */
diff --git a/arch/arm/mach-realview/include/mach/board-pba8.h b/arch/arm/mach-realview/include/mach/board-pba8.h
index 4dfc67a..f8ad328 100644
--- a/arch/arm/mach-realview/include/mach/board-pba8.h
+++ b/arch/arm/mach-realview/include/mach/board-pba8.h
@@ -59,15 +59,4 @@
 
 #define REALVIEW_PBA8_SYS_PLD_CTRL1		0x74
 
-/*
- * PBA8 PCI regions
- */
-#define REALVIEW_PBA8_PCI_BASE			0x90040000	/* PCI-X Unit base */
-#define REALVIEW_PBA8_PCI_IO_BASE		0x90050000	/* IO Region on AHB */
-#define REALVIEW_PBA8_PCI_MEM_BASE		0xA0000000	/* MEM Region on AHB */
-
-#define REALVIEW_PBA8_PCI_BASE_SIZE		0x10000		/* 16 Kb */
-#define REALVIEW_PBA8_PCI_IO_SIZE		0x1000		/* 4 Kb */
-#define REALVIEW_PBA8_PCI_MEM_SIZE		0x20000000	/* 512 MB */
-
 #endif	/* __ASM_ARCH_BOARD_PBA8_H */
diff --git a/arch/arm/mach-realview/include/mach/board-pbx.h b/arch/arm/mach-realview/include/mach/board-pbx.h
index 848bfff..93a975e 100644
--- a/arch/arm/mach-realview/include/mach/board-pbx.h
+++ b/arch/arm/mach-realview/include/mach/board-pbx.h
@@ -70,17 +70,6 @@
 #define REALVIEW_PBX_SYS_PLD_CTRL1		0x74
 
 /*
- * PBX PCI regions
- */
-#define REALVIEW_PBX_PCI_BASE			0x90040000	/* PCI-X Unit base */
-#define REALVIEW_PBX_PCI_IO_BASE		0x90050000	/* IO Region on AHB */
-#define REALVIEW_PBX_PCI_MEM_BASE		0xA0000000	/* MEM Region on AHB */
-
-#define REALVIEW_PBX_PCI_BASE_SIZE		0x10000		/* 16 Kb */
-#define REALVIEW_PBX_PCI_IO_SIZE		0x1000		/* 4 Kb */
-#define REALVIEW_PBX_PCI_MEM_SIZE		0x20000000	/* 512 MB */
-
-/*
  * Core tile identification (REALVIEW_SYS_PROCID)
  */
 #define REALVIEW_PBX_PROC_MASK          0xFF000000
diff --git a/arch/arm/mach-realview/include/mach/hardware.h b/arch/arm/mach-realview/include/mach/hardware.h
index 8a638d1..05ef223 100644
--- a/arch/arm/mach-realview/include/mach/hardware.h
+++ b/arch/arm/mach-realview/include/mach/hardware.h
@@ -23,6 +23,59 @@
 #define __ASM_ARCH_HARDWARE_H
 
 #include <asm/sizes.h>
+#include <asm/mach-types.h>
+
+/*
+ * PCI space virtual addresses
+ */
+#define REALVIEW_PCI_VIRT_BASE		0xF8000000
+#define REALVIEW_PCI_CFG_VIRT_BASE	0xF9000000
+#define PCIX_UNIT_BASE			0xF8000000
+#define REALVIEW_PCI_IO_VBASE		0xFA000000
+/*
+ * PCI space physical addresses and sizes
+ */
+#define REALVIEW_PB_PCI_BASE		0x90040000	/* PCI-X Unit base */
+#define REALVIEW_PB_PCI_BASE_SIZE	0x00010000	/* 4 Kb + 60Kb reserved */
+#define REALVIEW_PB_PCI_IO_BASE		0x90050000	/* IO Region on AHB */
+#define REALVIEW_PB_PCI_IO_SIZE		0x00010000	/* 64 Kb */
+#define REALVIEW_PB_PCI_IO_LIMIT       (REALVIEW_PB_PCI_IO_BASE + REALVIEW_PB_PCI_IO_SIZE - 1)
+#define REALVIEW_PB_PCI_MEM_BASE	0xA0000000	/* MEM Region on AHB */
+#define REALVIEW_PB_PCI_MEM_SIZE	0x20000000	/* 512 MB */
+
+#define REALVIEW_ISSP_REG_BASE		0x100E3000
+
+#ifdef CONFIG_PCI
+#if !defined(__ASSEMBLY__)
+static inline unsigned int pcibios_min_io(void)
+{
+	if (machine_is_realview_pb11mp() || machine_is_realview_pba8() ||
+	    machine_is_realview_pbx())
+		return REALVIEW_PB_PCI_IO_BASE;
+	else
+		return 0;
+}
+
+static inline unsigned int pcibios_min_mem(void)
+{
+	if (machine_is_realview_pb11mp() || machine_is_realview_pba8() ||
+	    machine_is_realview_pbx())
+		return REALVIEW_PB_PCI_MEM_BASE;
+	else
+		return 0;
+}
+#endif
+
+/*
+ * These are needed so that generic pci code doesn't know about our
+ * machine specific details.
+ */
+#define PCIBIOS_MIN_IO		pcibios_min_io()
+#define PCIBIOS_MIN_MEM		pcibios_min_mem()
+
+#define pcibios_assign_all_busses()     1
+
+#endif
 
 /* macro to get at IO space when running virtually */
 #ifdef CONFIG_MMU
diff --git a/arch/arm/mach-realview/include/mach/io.h b/arch/arm/mach-realview/include/mach/io.h
index f05bcdf..aa97d18 100644
--- a/arch/arm/mach-realview/include/mach/io.h
+++ b/arch/arm/mach-realview/include/mach/io.h
@@ -20,9 +20,25 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
-#define __io(a)		__typesafe_io(a)
+static inline void __iomem *__io(unsigned long addr)
+{
+#ifdef CONFIG_PCI
+	/* check for PCI I/O space */
+	if (addr >= REALVIEW_PB_PCI_IO_BASE && addr <= REALVIEW_PB_PCI_IO_LIMIT)
+		return (void __iomem *)((addr - REALVIEW_PB_PCI_IO_BASE) + REALVIEW_PCI_IO_VBASE);
+	else
+		return (void __iomem *)addr;
+#else
+	return (void __iomem *)addr;
+#endif
+}
+
+#define __io(a)		__io(a)
 #define __mem_pci(a)	(a)
 
 #endif
diff --git a/arch/arm/mach-realview/include/mach/platform.h b/arch/arm/mach-realview/include/mach/platform.h
index 1b77a27..75bddc4 100644
--- a/arch/arm/mach-realview/include/mach/platform.h
+++ b/arch/arm/mach-realview/include/mach/platform.h
@@ -77,6 +77,7 @@
 #define REALVIEW_SYS_BOOTCS_OFFSET           0x58
 #define REALVIEW_SYS_24MHz_OFFSET            0x5C
 #define REALVIEW_SYS_MISC_OFFSET             0x60
+#define REALVIEW_SYS_PCI_STAT_OFFSET	     0x6C
 #define REALVIEW_SYS_IOSEL_OFFSET            0x70
 #define REALVIEW_SYS_PROCID_OFFSET           0x84
 #define REALVIEW_SYS_TEST_OSC0_OFFSET        0xC0
@@ -111,6 +112,7 @@
 #define REALVIEW_SYS_BOOTCS                  (REALVIEW_SYS_BASE + REALVIEW_SYS_BOOTCS_OFFSET)
 #define REALVIEW_SYS_24MHz                   (REALVIEW_SYS_BASE + REALVIEW_SYS_24MHz_OFFSET)
 #define REALVIEW_SYS_MISC                    (REALVIEW_SYS_BASE + REALVIEW_SYS_MISC_OFFSET)
+#define REALVIEW_SYS_PCI_STAT		     (REALVIEW_SYS_BASE + REALVIEW_SYS_PCI_STAT_OFFSET)
 #define REALVIEW_SYS_IOSEL                   (REALVIEW_SYS_BASE + REALVIEW_SYS_IOSEL_OFFSET)
 #define REALVIEW_SYS_PROCID                  (REALVIEW_SYS_BASE + REALVIEW_SYS_PROCID_OFFSET)
 #define REALVIEW_SYS_TEST_OSC0               (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC0_OFFSET)
@@ -174,19 +176,6 @@
 #define REALVIEW_DMC_BASE             0x10018000	/* DMC configuration */
 #define REALVIEW_DMAC_BASE            0x10030000	/* DMA controller */
 
-/* PCI space */
-#define REALVIEW_PCI_BASE             0x41000000	/* PCI Interface */
-#define REALVIEW_PCI_CFG_BASE	      0x42000000
-#define REALVIEW_PCI_MEM_BASE0        0x44000000
-#define REALVIEW_PCI_MEM_BASE1        0x50000000
-#define REALVIEW_PCI_MEM_BASE2        0x60000000
-/* Sizes of above maps */
-#define REALVIEW_PCI_BASE_SIZE	       0x01000000
-#define REALVIEW_PCI_CFG_BASE_SIZE    0x02000000
-#define REALVIEW_PCI_MEM_BASE0_SIZE   0x0c000000	/* 32Mb */
-#define REALVIEW_PCI_MEM_BASE1_SIZE   0x10000000	/* 256Mb */
-#define REALVIEW_PCI_MEM_BASE2_SIZE   0x10000000	/* 256Mb */
-
 #define REALVIEW_SDRAM67_BASE         0x70000000	/* SDRAM banks 6 and 7 */
 #define REALVIEW_LT_BASE              0x80000000	/* Logic Tile expansion */
 

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/6] ARM Realview PCIX IRQ include file changes
  2010-10-20 13:02 [PATCH 0/6] Add PCI support for ARM RealView boards Colin Tuckley
                   ` (2 preceding siblings ...)
  2010-10-20 13:03 ` [PATCH 3/6] ARM Realview PCIX map include file changes Colin Tuckley
@ 2010-10-20 13:03 ` Colin Tuckley
  2010-10-20 13:03 ` [PATCH 5/6] ARM Realview PCIX board " Colin Tuckley
  2010-10-20 13:03 ` [PATCH 6/6] ARM Realview PCIX build " Colin Tuckley
  5 siblings, 0 replies; 15+ messages in thread
From: Colin Tuckley @ 2010-10-20 13:03 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the Interrupt definitions for the PCI
support on the Realview boards.

Signed-off-by: Colin Tuckley <colin.tuckley@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---

 arch/arm/mach-realview/include/mach/irqs-pb11mp.h |   11 +++++++++++
 arch/arm/mach-realview/include/mach/irqs-pba8.h   |    7 ++++++-
 arch/arm/mach-realview/include/mach/irqs-pbx.h    |    7 ++++++-
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-realview/include/mach/irqs-pb11mp.h b/arch/arm/mach-realview/include/mach/irqs-pb11mp.h
index 34e255a..cd3e3e6 100644
--- a/arch/arm/mach-realview/include/mach/irqs-pb11mp.h
+++ b/arch/arm/mach-realview/include/mach/irqs-pb11mp.h
@@ -95,6 +95,17 @@
 #define IRQ_PB11MP_TSPEN	(IRQ_PB11MP_GIC_START + 30)	/* Touchscreen pen */
 #define IRQ_PB11MP_TSKPAD	(IRQ_PB11MP_GIC_START + 31)	/* Touchscreen keypad */
 
+/* These PCI/PCIe IRQ definitions are here as placeholders
+ * The PCI code actually calculates the irq used at runtime */
+#define IRQ_PB11MP_PCI0		(IRQ_PB11MP_GIC_START + 50)
+#define IRQ_PB11MP_PCI1		(IRQ_PB11MP_GIC_START + 51)
+#define IRQ_PB11MP_PCI2		(IRQ_PB11MP_GIC_START + 52)
+#define IRQ_PB11MP_PCI3		(IRQ_PB11MP_GIC_START + 53)
+#define IRQ_PB11MP_PCIE0	(IRQ_PB11MP_GIC_START + 54)
+#define IRQ_PB11MP_PCIE1	(IRQ_PB11MP_GIC_START + 55)
+#define IRQ_PB11MP_PCIE2	(IRQ_PB11MP_GIC_START + 56)
+#define IRQ_PB11MP_PCIE3	(IRQ_PB11MP_GIC_START + 57)
+
 #define IRQ_PB11MP_SMC		-1
 #define IRQ_PB11MP_SCTL		-1
 
diff --git a/arch/arm/mach-realview/include/mach/irqs-pba8.h b/arch/arm/mach-realview/include/mach/irqs-pba8.h
index 4a88a4e..da6d583 100644
--- a/arch/arm/mach-realview/include/mach/irqs-pba8.h
+++ b/arch/arm/mach-realview/include/mach/irqs-pba8.h
@@ -61,11 +61,16 @@
 
 #define IRQ_PBA8_PMU		(IRQ_PBA8_GIC_START + 47)	/* Cortex-A8 PMU */
 
-/* ... */
+/* These PCI/PCIe IRQ definitions are here as placeholders
+ * The PCI code actually calculates the irq used at runtime */
 #define IRQ_PBA8_PCI0		(IRQ_PBA8_GIC_START + 50)
 #define IRQ_PBA8_PCI1		(IRQ_PBA8_GIC_START + 51)
 #define IRQ_PBA8_PCI2		(IRQ_PBA8_GIC_START + 52)
 #define IRQ_PBA8_PCI3		(IRQ_PBA8_GIC_START + 53)
+#define IRQ_PBA8_PCIE0		(IRQ_PBA8_GIC_START + 54)
+#define IRQ_PBA8_PCIE1		(IRQ_PBA8_GIC_START + 55)
+#define IRQ_PBA8_PCIE2		(IRQ_PBA8_GIC_START + 56)
+#define IRQ_PBA8_PCIE3		(IRQ_PBA8_GIC_START + 57)
 
 #define IRQ_PBA8_SMC		-1
 #define IRQ_PBA8_SCTL		-1
diff --git a/arch/arm/mach-realview/include/mach/irqs-pbx.h b/arch/arm/mach-realview/include/mach/irqs-pbx.h
index 206a300..f661702 100644
--- a/arch/arm/mach-realview/include/mach/irqs-pbx.h
+++ b/arch/arm/mach-realview/include/mach/irqs-pbx.h
@@ -76,11 +76,16 @@
 #define IRQ_PBX_PMU_CPU2        (IRQ_PBX_GIC_START + 46)
 #define IRQ_PBX_PMU_CPU3        (IRQ_PBX_GIC_START + 47)
 
-/* ... */
+/* These PCI/PCIe IRQ definitions are here as placeholders
+ * The PCI code actually calculates the irq used at runtime */
 #define IRQ_PBX_PCI0		(IRQ_PBX_GIC_START + 50)
 #define IRQ_PBX_PCI1		(IRQ_PBX_GIC_START + 51)
 #define IRQ_PBX_PCI2		(IRQ_PBX_GIC_START + 52)
 #define IRQ_PBX_PCI3		(IRQ_PBX_GIC_START + 53)
+#define IRQ_PBX_PCIE0		(IRQ_PBX_GIC_START + 54)
+#define IRQ_PBX_PCIE1		(IRQ_PBX_GIC_START + 55)
+#define IRQ_PBX_PCIE2		(IRQ_PBX_GIC_START + 56)
+#define IRQ_PBX_PCIE3		(IRQ_PBX_GIC_START + 57)
 
 #define IRQ_PBX_SMC		-1
 #define IRQ_PBX_SCTL		-1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/6] ARM Realview PCIX board file changes
  2010-10-20 13:02 [PATCH 0/6] Add PCI support for ARM RealView boards Colin Tuckley
                   ` (3 preceding siblings ...)
  2010-10-20 13:03 ` [PATCH 4/6] ARM Realview PCIX IRQ " Colin Tuckley
@ 2010-10-20 13:03 ` Colin Tuckley
  2010-10-20 13:03 ` [PATCH 6/6] ARM Realview PCIX build " Colin Tuckley
  5 siblings, 0 replies; 15+ messages in thread
From: Colin Tuckley @ 2010-10-20 13:03 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the PCI support to the board files
for the Realview Northbridge boards.

Signed-off-by: Colin Tuckley <colin.tuckley@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---

 arch/arm/mach-realview/realview_pb11mp.c |   18 ++++++++++++++++++
 arch/arm/mach-realview/realview_pba8.c   |   16 +++++++++++++---
 arch/arm/mach-realview/realview_pbx.c    |   14 ++++++++++++--
 3 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index d591bc0..c84bda6 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -95,6 +95,24 @@ static struct map_desc realview_pb11mp_io_desc[] __initdata = {
 		.length		= SZ_8K,
 		.type		= MT_DEVICE,
 	},
+#ifdef CONFIG_PCI
+	{
+		.virtual	= PCIX_UNIT_BASE,
+		.pfn		= __phys_to_pfn(REALVIEW_PB_PCI_BASE),
+		.length		= REALVIEW_PB_PCI_BASE_SIZE,
+		.type		= MT_DEVICE,
+	 }, {
+		.virtual	= REALVIEW_PCI_IO_VBASE,
+		.pfn		= __phys_to_pfn(REALVIEW_PB_PCI_IO_BASE),
+		.length		= REALVIEW_PB_PCI_IO_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual        = IO_ADDRESS(REALVIEW_ISSP_REG_BASE),
+		.pfn            = __phys_to_pfn(REALVIEW_ISSP_REG_BASE),
+		.length         = SZ_4K,
+		.type           = MT_DEVICE,
+	},
+#endif
 #ifdef CONFIG_DEBUG_LL
 	{
 		.virtual	= IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE),
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 6c37621..09bcd46 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -80,9 +80,19 @@ static struct map_desc realview_pba8_io_desc[] __initdata = {
 #ifdef CONFIG_PCI
 	{
 		.virtual	= PCIX_UNIT_BASE,
-		.pfn		= __phys_to_pfn(REALVIEW_PBA8_PCI_BASE),
-		.length		= REALVIEW_PBA8_PCI_BASE_SIZE,
-		.type		= MT_DEVICE
+		.pfn		= __phys_to_pfn(REALVIEW_PB_PCI_BASE),
+		.length		= REALVIEW_PB_PCI_BASE_SIZE,
+		.type		= MT_DEVICE,
+	 }, {
+		.virtual	= REALVIEW_PCI_IO_VBASE,
+		.pfn		= __phys_to_pfn(REALVIEW_PB_PCI_IO_BASE),
+		.length		= REALVIEW_PB_PCI_IO_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(REALVIEW_ISSP_REG_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_ISSP_REG_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
 	},
 #endif
 #ifdef CONFIG_DEBUG_LL
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 9428eff..5cd0a9a 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -81,8 +81,18 @@ static struct map_desc realview_pbx_io_desc[] __initdata = {
 #ifdef CONFIG_PCI
 	{
 		.virtual	= PCIX_UNIT_BASE,
-		.pfn		= __phys_to_pfn(REALVIEW_PBX_PCI_BASE),
-		.length		= REALVIEW_PBX_PCI_BASE_SIZE,
+		.pfn		= __phys_to_pfn(REALVIEW_PB_PCI_BASE),
+		.length		= REALVIEW_PB_PCI_BASE_SIZE,
+		.type		= MT_DEVICE,
+	 }, {
+		.virtual	= REALVIEW_PCI_IO_VBASE,
+		.pfn		= __phys_to_pfn(REALVIEW_PB_PCI_IO_BASE),
+		.length		= REALVIEW_PB_PCI_IO_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(REALVIEW_ISSP_REG_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_ISSP_REG_BASE),
+		.length		= SZ_4K,
 		.type		= MT_DEVICE,
 	},
 #endif

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/6] ARM Realview PCIX build file changes
  2010-10-20 13:02 [PATCH 0/6] Add PCI support for ARM RealView boards Colin Tuckley
                   ` (4 preceding siblings ...)
  2010-10-20 13:03 ` [PATCH 5/6] ARM Realview PCIX board " Colin Tuckley
@ 2010-10-20 13:03 ` Colin Tuckley
  2010-10-20 21:32   ` Arnd Bergmann
  5 siblings, 1 reply; 15+ messages in thread
From: Colin Tuckley @ 2010-10-20 13:03 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds PCI support for the Realview boards
to the mach-realview build system.

Signed-off-by: Colin Tuckley <colin.tuckley@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---

 arch/arm/Kconfig                |    6 +++++-
 arch/arm/mach-realview/Makefile |    6 ++++++
 2 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9c26ba7..05c7aa2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1143,7 +1143,9 @@ config ISA_DMA_API
 	bool
 
 config PCI
-	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
+	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || \
+	ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX || \
+	MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBA8 || MACH_REALVIEW_PBX
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -1171,6 +1173,8 @@ config PCI_HOST_ITE8152
 
 source "drivers/pci/Kconfig"
 
+source "drivers/pci/pcie/Kconfig"
+
 source "drivers/pcmcia/Kconfig"
 
 endmenu
diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
index a01b76b..bb2d414 100644
--- a/arch/arm/mach-realview/Makefile
+++ b/arch/arm/mach-realview/Makefile
@@ -10,4 +10,10 @@ obj-$(CONFIG_MACH_REALVIEW_PBA8)	+= realview_pba8.o
 obj-$(CONFIG_MACH_REALVIEW_PBX)		+= realview_pbx.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
+ifeq ($(CONFIG_PCI),y)
+obj-$(CONFIG_MACH_REALVIEW_PB11MP)	+= pcix.o
+obj-$(CONFIG_MACH_REALVIEW_PBA8)	+= pcix.o
+obj-$(CONFIG_MACH_REALVIEW_PBX)		+= pcix.o
+endif
+
 obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 1/6] Realview PCIX support - add main support module code
  2010-10-20 13:02 ` [PATCH 1/6] Realview PCIX support - add main support module code Colin Tuckley
@ 2010-10-20 21:16   ` Arnd Bergmann
  2010-10-21 10:03     ` Colin Tuckley
  2010-10-28 14:09     ` Russell King - ARM Linux
  2010-10-28 14:02   ` Russell King - ARM Linux
  1 sibling, 2 replies; 15+ messages in thread
From: Arnd Bergmann @ 2010-10-20 21:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 20 October 2010 15:02:54 Colin Tuckley wrote:
> This patch adds pcix.c - the main pci sub-system code for
> the RealView boards which have PCI and PCIe interfaces
> via a custom NEC northbridge chip and two bridges.

How about merging this patch with into the last one? No point
adding code that doesn't even get seen by the compiler.

> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/ptrace.h>

ptrace.h?

> +/* PCI-X Configuration registers */
> +#define PCI_VENID			0x00
> +#define PCI_DEVID			0x02
> +#define PCI_COMMAND			0x04
> ... 

These don't belong here -- just use the common definitions
from pci_regs.h. The extended config registers starting at 0x40
are obviously fine here.

> +static void realview_pb_pcix_unit_init(void)
> +{
> +	u32 data = readl(PCIX_UNIT_BASE + PCI_UNITCNT);
> +
> +	if (data & 0x10)
> +		writel(0x00000000, PCIX_UNIT_BASE + PCI_PRST); /* Assert PCI reset */
> +	else {
> +		printk(KERN_ERR "Error: PCI-X unit not in PCI-X mode.\n");
> +		writel(data | 0x80000000, PCIX_UNIT_BASE + PCI_UNITCNT);
> +	}
> +
> +	writew(0x0006, PCIX_UNIT_BASE + PCI_COMMAND); /* Master-Memory enable */
> +	writew(0xfb30, PCIX_UNIT_BASE + PCI_STATUS);  /* Error bit clear */

How about a temporary

	void __iomem *base = PCIX_UNIT_BASE;

as a shortcut so you don't have to write PCIX_UNIT_BASE every time.
> +#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
> +	/* 512MB of DMA capable RAM is available - mapped at 0x70000000
> +	 * Note :- 0x70000000 is *not* on a 512MB boundary so it
> +	 * must be mapped in two parts */
> +	/* Window#0 256MB and enable */
> +	writel(0x0fff0001, PCIX_UNIT_BASE + PCI_PTMEMMSK0);
> +	/* Window#1 256MB and enable */
> +	writel(0x0fff0001, PCIX_UNIT_BASE + PCI_PTMEMMSK1);
> +
> +	/* Window base address setting */
> +	/* Memory Base Address, Ptrefetch Disable, 64bit */
> +	writel(0x70000004, PCIX_UNIT_BASE + PCI_PTBADDR0L);
> +	/* Memory Base Address[63:32] */
> +	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR0M);
> +
> +	/* Memory Base Address, Ptrefetch Disable, 64bit */
> +	writel(0x80000004, PCIX_UNIT_BASE + PCI_PTBADDR1L);
> +	/* Memory Base Address[63:32] */
> +	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR1M);

If you write PHYS_OFFSET into PCI_PTBADDR1L, you don't need
the #ifdef, and the code gets reusable on platforms that have
yet another phys offset.

> +	/* OnChipBus Address#0[35:24] */
> +	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTMEMSEG0);
> +	/* OnChipBus Address#1[35:24] */
> +	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTMEMSEG1);
> +
> +	/* 66MHz, 64bit device */
> +	writel(0x00010000, PCIX_UNIT_BASE + PCI_PCIXSTAT);
> +	/* Interrupt Mask */
> +	writel(0x00000000, PCIX_UNIT_BASE + PCI_PINTXMASK);
> +	/* Enable PCI error status */
> +	writel(0x000307f7, PCIX_UNIT_BASE + PCI_PERRMASK);
> +	/* Clear PCI error status */
> +	writel(0x000307f7, PCIX_UNIT_BASE + PCI_PERRSTAT);
> +	/* Enable count out */
> +	writel(0x10FFFFFF, PCIX_UNIT_BASE + PCI_CNTOTIMER);
> +
> +	realview_pb_pcix_sync();
> +	udelay(1500); /* Allow hardware to settle */

You should not need to delay for that long. What is the problem
here? If the sync operation actually does a sync, you should not
need to wait again, right?

Also, you don't seem to be in atomic context, so you can just
use msleep(2) instead.

> +void realview_pb_pcix_set_attr(unsigned int tag)
> +{
> +	/* Get Device and Funcion number */
> +	u32 data = readl(PCIX_UNIT_BASE + PCI_PCIXSTAT) & 0x0ff;
> +	/* attribute set */
> +	writel(tag | (data << 8), PCIX_UNIT_BASE + PCI_CFGATTR);
> +}

Should this function be static? It appears to be only used in this
file.

> +int realview_pb_pcix_set_config(u32 bus, u32 dev, u32 func, int offset)

Same here.

> +{
> +	u32 mode;
> +	u32 config_addr;
> +
> +	writel(0x000307F7, PCIX_UNIT_BASE + PCI_PERRSTAT); /* clear error bit */
> +	writew(0xfb30, PCIX_UNIT_BASE + PCI_STATUS);	   /* error bit clear */

I would guess that you need locking here, two drivers might simultaneously be
accessing config space on different CPUs, or you might have kernel preemption
enabled and get preempted between the register accesses.

> +int realview_pb_pci_read_config(struct pci_bus *pbus, u32 devfn,
> +				     int offset, int size, u32 *data)
> +{
> +	u32 bus = pbus->number;
> +	u32 slot = PCI_SLOT(devfn);
> +	u32 function = PCI_FUNC(devfn);

Here too.

Why are these functions called realview_pb_pci_* while the others are called
realview_pb_pcix_*? I would expect that the pci name refers to the Xilinx
pci bus while the pcix name is the NEC pci-x.

> +static int __init pci_realview_pb_setup(int nr, struct pci_sys_data *sys)
> +{
> +	if (machine_is_realview_pb11mp())
> +		irq_gic_start = IRQ_PB11MP_GIC_START;
> +	else
> +		irq_gic_start = IRQ_PBA8_GIC_START;

Can you remove the board specific tests from the common file? Just pass the
interrupt number through an init function that can get called by the
board file, which will make reuse much easier if other platforms use the
same hardware.

> +	sys->io_offset = REALVIEW_PB_PCI_IO_BASE;

Why do you need to set io_offset?

> +static void __init pci_realview_pb_preinit(void)
> +{
> +	u32 data = readl(__io_address(REALVIEW_SYS_PCI_STAT));
> +	data &= ~0x00000100; /* Clear the Clock Control bit */
> +	writel(data, __io_address(REALVIEW_SYS_PCI_STAT));
> +	udelay(1500); /* Allow hardware to settle */
> +}

msleep

> +static struct hw_pci realview_pb_pci __initdata = {
> +	.swizzle		= NULL,

Really no swizzling? That is very unusual, almost everyone needs to set 
pci_common_swizzle here to make bridges work.

> +static int __init realview_pb_pci_init(void)
> +{
> +	if (machine_is_realview_pb11mp() ||
> +	    machine_is_realview_pba8() || machine_is_realview_pbx())
> +		pci_common_init(&realview_pb_pci);
> +	return 0;
> +}
> +
> +subsys_initcall(realview_pb_pci_init);

Why not call this from the board file?

	Arnd

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 3/6] ARM Realview PCIX map include file changes
  2010-10-20 13:03 ` [PATCH 3/6] ARM Realview PCIX map include file changes Colin Tuckley
@ 2010-10-20 21:28   ` Arnd Bergmann
  0 siblings, 0 replies; 15+ messages in thread
From: Arnd Bergmann @ 2010-10-20 21:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 20 October 2010 15:03:05 Colin Tuckley wrote:
> This patch adds the memory map PCI support to the include
> files for the Realview Northbridge based boards.
> 
>  #include <asm/sizes.h>
> +#include <asm/mach-types.h>
> +
> +/*
> + * PCI space virtual addresses
> + */
> +#define REALVIEW_PCI_VIRT_BASE		0xF8000000
> +#define REALVIEW_PCI_CFG_VIRT_BASE	0xF9000000
> +#define PCIX_UNIT_BASE			0xF8000000
> +#define REALVIEW_PCI_IO_VBASE		0xFA000000

Please use the correct type virt base definition, i.e. void __iomem *, so you can
use readl/writel on them.

We should also coordinate this with the xilinx PCI patches that I sent.
We are both using the same virtual base for the IO range (fa00000),
but I named the macro differently (REALVIEW_PCI_IO_VIRT_BASE). I'm fine
either way, but there is no point having two different names for the
same thing.

> +/*
> + * PCI space physical addresses and sizes
> + */
> +#define REALVIEW_PB_PCI_BASE		0x90040000	/* PCI-X Unit base */
> +#define REALVIEW_PB_PCI_BASE_SIZE	0x00010000	/* 4 Kb + 60Kb reserved */
> +#define REALVIEW_PB_PCI_IO_BASE		0x90050000	/* IO Region on AHB */
> +#define REALVIEW_PB_PCI_IO_SIZE		0x00010000	/* 64 Kb */
> +#define REALVIEW_PB_PCI_IO_LIMIT       (REALVIEW_PB_PCI_IO_BASE + REALVIEW_PB_PCI_IO_SIZE - 1)
> +#define REALVIEW_PB_PCI_MEM_BASE	0xA0000000	/* MEM Region on AHB */
> +#define REALVIEW_PB_PCI_MEM_SIZE	0x20000000	/* 512 MB */

The naming for these seems screwed up -- it does not apply to all realview pb.

> +/*
> + * These are needed so that generic pci code doesn't know about our
> + * machine specific details.
> + */
> +#define PCIBIOS_MIN_IO		pcibios_min_io()
> +#define PCIBIOS_MIN_MEM		pcibios_min_mem()

PCIBIOS_MIN_IO should always just be 0x1000, PCIBIOS_MIN_MEM is generally
ignored.

>  #define IO_SPACE_LIMIT 0xffffffff

IO_SPACE_LIMIT is also wrong, it should not be larger than the space you have
reserved at 0xFA000000, possibly just 0xffff, which is enough in practice.

> +static inline void __iomem *__io(unsigned long addr)
> +{
> +#ifdef CONFIG_PCI
> +	/* check for PCI I/O space */
> +	if (addr >= REALVIEW_PB_PCI_IO_BASE && addr <= REALVIEW_PB_PCI_IO_LIMIT)
> +		return (void __iomem *)((addr - REALVIEW_PB_PCI_IO_BASE) + REALVIEW_PCI_IO_VBASE);
> +	else
> +		return (void __iomem *)addr;
> +#else
> +	return (void __iomem *)addr;
> +#endif
> +}

No need for the #ifdef here, if you don't have PCI, nobody will call __io anyway.

Just make this

#define __io(x) (REALVIEW_PCI_IO_VBASE + x)

	Arnd

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 6/6] ARM Realview PCIX build file changes
  2010-10-20 13:03 ` [PATCH 6/6] ARM Realview PCIX build " Colin Tuckley
@ 2010-10-20 21:32   ` Arnd Bergmann
  0 siblings, 0 replies; 15+ messages in thread
From: Arnd Bergmann @ 2010-10-20 21:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 20 October 2010 15:03:22 Colin Tuckley wrote:
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 9c26ba7..05c7aa2 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1143,7 +1143,9 @@ config ISA_DMA_API
>         bool
>  
>  config PCI
> -       bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
> +       bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || \
> +       ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX || \
> +       MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBA8 || MACH_REALVIEW_PBX
>         help
>           Find out whether you have a PCI motherboard. PCI is the name of a
>           bus system, i.e. the way the CPU talks to the other stuff inside
> @@ -1171,6 +1173,8 @@ config PCI_HOST_ITE8152
>  
>  source "drivers/pci/Kconfig"
>  
> +source "drivers/pci/pcie/Kconfig"
> +
>  source "drivers/pcmcia/Kconfig"
>  
>  endmenu

Why not have a new Kconfig symbol here:

config REALVIEW_PCIX
	bool "PCI-X support for Realview-PB11MP/PB-A8/PBX"
	depends on MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBA8 || MACH_REALVIEW_PBX
	select PCI
	
and

> @@ -10,4 +10,10 @@ obj-$(CONFIG_MACH_REALVIEW_PBA8)     += realview_pba8.o
>  obj-$(CONFIG_MACH_REALVIEW_PBX)                += realview_pbx.o
>  obj-$(CONFIG_SMP)                      += platsmp.o headsmp.o
>  obj-$(CONFIG_HOTPLUG_CPU)              += hotplug.o
> +ifeq ($(CONFIG_PCI),y)
> +obj-$(CONFIG_MACH_REALVIEW_PB11MP)     += pcix.o
> +obj-$(CONFIG_MACH_REALVIEW_PBA8)       += pcix.o
> +obj-$(CONFIG_MACH_REALVIEW_PBX)                += pcix.o
> +endif
> +
>  obj-$(CONFIG_LOCAL_TIMERS)             += localtimer.o

obj-$(CONFIG_REALVIEW_PCIX)		+= pcix.o

	Arnd

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/6] Realview PCIX support - add main support module code
  2010-10-20 21:16   ` Arnd Bergmann
@ 2010-10-21 10:03     ` Colin Tuckley
  2010-10-21 12:44       ` Arnd Bergmann
  2010-10-28 14:09     ` Russell King - ARM Linux
  1 sibling, 1 reply; 15+ messages in thread
From: Colin Tuckley @ 2010-10-21 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 20 October 2010 22:17

First, I need to point out that this code and the patches are quite old.
They have been used internally since before 2.6.33 and I then forward ported
them for submission. I don't have a lot of time to do a proper
re-validation.

> How about merging this patch with into the last one? No point
> adding code that doesn't even get seen by the compiler.

The idea was to keep the series in logical chunks and since this was already
quite large I kept it separate.

> ptrace.h?

Oops, a left over from some debugging I suspect - removed.

> > +/* PCI-X Configuration registers */
> > +#define PCI_VENID			0x00
> > +#define PCI_DEVID			0x02
> > +#define PCI_COMMAND			0x04
> > ...
> 
> These don't belong here -- just use the common definitions
> from pci_regs.h. The extended config registers starting at 0x40
> are obviously fine here.

Removed, except for the ones that use names that match the chip
documentation.

> How about a temporary
> 	void __iomem *base = PCIX_UNIT_BASE;
> as a shortcut so you don't have to write PCIX_UNIT_BASE every time.

I believe it's clearer the way it is.

> > +#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
> > +	/* 512MB of DMA capable RAM is available - mapped at 0x70000000
> > +	 * Note :- 0x70000000 is *not* on a 512MB boundary so it
> > +	 * must be mapped in two parts */
> > +	/* Window#0 256MB and enable */
> > +	writel(0x0fff0001, PCIX_UNIT_BASE + PCI_PTMEMMSK0);
> > +	/* Window#1 256MB and enable */
> > +	writel(0x0fff0001, PCIX_UNIT_BASE + PCI_PTMEMMSK1);
> > +
> > +	/* Window base address setting */
> > +	/* Memory Base Address, Ptrefetch Disable, 64bit */
> > +	writel(0x70000004, PCIX_UNIT_BASE + PCI_PTBADDR0L);
> > +	/* Memory Base Address[63:32] */
> > +	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR0M);
> > +
> > +	/* Memory Base Address, Ptrefetch Disable, 64bit */
> > +	writel(0x80000004, PCIX_UNIT_BASE + PCI_PTBADDR1L);
> > +	/* Memory Base Address[63:32] */
> > +	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR1M);
> 
> If you write PHYS_OFFSET into PCI_PTBADDR1L, you don't need
> the #ifdef, and the code gets reusable on platforms that have
> yet another phys offset.

That wouldn't allow for the differences in size of DMA capable RAM. I know
it could be computed but I think this makes it clearer.

> > +	realview_pb_pcix_sync();
> > +	udelay(1500); /* Allow hardware to settle */
> 
> You should not need to delay for that long. What is the problem
> here? If the sync operation actually does a sync, you should not
> need to wait again, right?

This is copied from the NEC docs and example code. It isn't really a sync
(as in waiting for something) it's more a device to get the hardware into a
known state. It works and I don't have time to do the testing required if I
start changing things like that which could be critical.

> > +void realview_pb_pcix_set_attr(unsigned int tag)
> > +{
> > +	/* Get Device and Funcion number */
> > +	u32 data = readl(PCIX_UNIT_BASE + PCI_PCIXSTAT) & 0x0ff;
> > +	/* attribute set */
> > +	writel(tag | (data << 8), PCIX_UNIT_BASE + PCI_CFGATTR);
> > +}
> 
> Should this function be static? It appears to be only used in this
> file.
> > +int realview_pb_pcix_set_config(u32 bus, u32 dev, u32 func, int
> offset)

True, I thought I'd found all of those type of cases - fixed.

> > +{
> > +	u32 mode;
> > +	u32 config_addr;
> > +
> > +	writel(0x000307F7, PCIX_UNIT_BASE + PCI_PERRSTAT); /* clear error
> bit */
> > +	writew(0xfb30, PCIX_UNIT_BASE + PCI_STATUS);	   /* error bit
> clear */
> 
> I would guess that you need locking here, two drivers might
> simultaneously be
> accessing config space on different CPUs, or you might have kernel
> preemption
> enabled and get preempted between the register accesses.

Hmm... you could be correct, however we have done a lot of testing on SMP
systems with no problems. I'll have a chat with Catalin about this.

> Why are these functions called realview_pb_pci_* while the others are
> called
> realview_pb_pcix_*? I would expect that the pci name refers to the
> Xilinx
> pci bus while the pcix name is the NEC pci-x.

The original author probably cloned the pci code as a starting point. I've
fixed them.

> > +static int __init pci_realview_pb_setup(int nr, struct pci_sys_data
> *sys)
> > +{
> > +	if (machine_is_realview_pb11mp())
> > +		irq_gic_start = IRQ_PB11MP_GIC_START;
> > +	else
> > +		irq_gic_start = IRQ_PBA8_GIC_START;
> 
> Can you remove the board specific tests from the common file? Just pass
> the
> interrupt number through an init function that can get called by the
> board file, which will make reuse much easier if other platforms use
> the same hardware.

There will not be any more mach-realview board designs, certainly none that
use this root complex.

> > +	sys->io_offset = REALVIEW_PB_PCI_IO_BASE;
> 
> Why do you need to set io_offset?

I haven't investigated this. Is it something that is really wrong? Or just a
different way of doing things?

> Really no swizzling? That is very unusual, almost everyone needs to set
> pci_common_swizzle here to make bridges work.

No generic swizzling, it's done during the bus scan because it's very
non-standard due to the hardware design.

> > +static int __init realview_pb_pci_init(void)
> > +{
> > +	if (machine_is_realview_pb11mp() ||
> > +	    machine_is_realview_pba8() || machine_is_realview_pbx())
> > +		pci_common_init(&realview_pb_pci);
> > +	return 0;
> > +}
> > +
> > +subsys_initcall(realview_pb_pci_init);
> 
> Why not call this from the board file?

Don't know, as I said before I'm not the original author and we changed as
little as possible while getting it to work.

Regards,

Colin

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/6] Realview PCIX support - add main support module code
  2010-10-21 10:03     ` Colin Tuckley
@ 2010-10-21 12:44       ` Arnd Bergmann
  0 siblings, 0 replies; 15+ messages in thread
From: Arnd Bergmann @ 2010-10-21 12:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 21 October 2010, Colin Tuckley wrote:
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > Sent: 20 October 2010 22:17
> 
> First, I need to point out that this code and the patches are quite old.
> They have been used internally since before 2.6.33 and I then forward ported
> them for submission. 

Yes, I could see that from the code ;-)

> > How about merging this patch with into the last one? No point
> > adding code that doesn't even get seen by the compiler.
> 
> The idea was to keep the series in logical chunks and since this was already
> quite large I kept it separate.

Logical chunks are good, but the last one was not really logical.
If you really want smaller patches, you can split the initialization
from the run-time (config space, interrupts, ...) handling. I don't think
it's too big though, new drivers just tend be be much bigger than incremental
patches on existing code.

> > How about a temporary
> > 	void __iomem *base = PCIX_UNIT_BASE;
> > as a shortcut so you don't have to write PCIX_UNIT_BASE every time.
> 
> I believe it's clearer the way it is.

Ok.
 
> > > +#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
> > > +	/* 512MB of DMA capable RAM is available - mapped at 0x70000000
> > > +	 * Note :- 0x70000000 is *not* on a 512MB boundary so it
> > > +	 * must be mapped in two parts */
> > > +	/* Window#0 256MB and enable */
> > > +	writel(0x0fff0001, PCIX_UNIT_BASE + PCI_PTMEMMSK0);
> > > +	/* Window#1 256MB and enable */
> > > +	writel(0x0fff0001, PCIX_UNIT_BASE + PCI_PTMEMMSK1);
> > > +
> > > +	/* Window base address setting */
> > > +	/* Memory Base Address, Ptrefetch Disable, 64bit */
> > > +	writel(0x70000004, PCIX_UNIT_BASE + PCI_PTBADDR0L);
> > > +	/* Memory Base Address[63:32] */
> > > +	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR0M);
> > > +
> > > +	/* Memory Base Address, Ptrefetch Disable, 64bit */
> > > +	writel(0x80000004, PCIX_UNIT_BASE + PCI_PTBADDR1L);
> > > +	/* Memory Base Address[63:32] */
> > > +	writel(0x00000000, PCIX_UNIT_BASE + PCI_PTBADDR1M);
> > 
> > If you write PHYS_OFFSET into PCI_PTBADDR1L, you don't need
> > the #ifdef, and the code gets reusable on platforms that have
> > yet another phys offset.
> 
> That wouldn't allow for the differences in size of DMA capable RAM. I know
> it could be computed but I think this makes it clearer.

It certainly didn't make it clear from my perspective -- I didn't
notice that the sizes are different here ;-).

I'm hoping we can eliminate the CONFIG_REALVIEW_HIGH_PHYS_OFFSET
option at some point, and turn PHYS_OFFSET into a run-time option.
If you calculate the values, there's one less place to fix then.

> > > +	realview_pb_pcix_sync();
> > > +	udelay(1500); /* Allow hardware to settle */
> > 
> > You should not need to delay for that long. What is the problem
> > here? If the sync operation actually does a sync, you should not
> > need to wait again, right?
> 
> This is copied from the NEC docs and example code. It isn't really a sync
> (as in waiting for something) it's more a device to get the hardware into a
> known state. It works and I don't have time to do the testing required if I
> start changing things like that which could be critical.

Then just add this explanation to the comment and turn it into an msleep().

> > > +{
> > > +	u32 mode;
> > > +	u32 config_addr;
> > > +
> > > +	writel(0x000307F7, PCIX_UNIT_BASE + PCI_PERRSTAT); /* clear error
> > bit */
> > > +	writew(0xfb30, PCIX_UNIT_BASE + PCI_STATUS);	   /* error bit
> > clear */
> > 
> > I would guess that you need locking here, two drivers might
> > simultaneously be
> > accessing config space on different CPUs, or you might have kernel
> > preemption
> > enabled and get preempted between the register accesses.
> 
> Hmm... you could be correct, however we have done a lot of testing on SMP
> systems with no problems. I'll have a chat with Catalin about this.

PCI config spaces are extremely rare once the system is booted up.
I'm not surprised that it works in practice, but that doesn't make it
correct ;-)

> > > +static int __init pci_realview_pb_setup(int nr, struct pci_sys_data
> > *sys)
> > > +{
> > > +	if (machine_is_realview_pb11mp())
> > > +		irq_gic_start = IRQ_PB11MP_GIC_START;
> > > +	else
> > > +		irq_gic_start = IRQ_PBA8_GIC_START;
> > 
> > Can you remove the board specific tests from the common file? Just pass
> > the
> > interrupt number through an init function that can get called by the
> > board file, which will make reuse much easier if other platforms use
> > the same hardware.
> 
> There will not be any more mach-realview board designs, certainly none that
> use this root complex.

Yes, but:

1. There might be other companies that have licensed the same macro for
their SoCs.

2. I was discussing with Peter Maydell to implement this in qemu as well,
so it could be used on all ARM platforms. Ideally you should be able
to specify the settings using a device tree once that gets supported, so
you can have a PCI bus in an emulated platform that normally doesn't have
one. Don't worry about the device tree stuff now, but it would really be
helpful to allow configuring this from outside (same as the phys offset.

3. I hope we can eventually merge the realview and versatile express
platforms so it becomes possible to build a generic kernel for them
all.

> > > +	sys->io_offset = REALVIEW_PB_PCI_IO_BASE;
> > 
> > Why do you need to set io_offset?
> 
> I haven't investigated this. Is it something that is really wrong? Or just a
> different way of doing things?

It looks wrong to me, but I haven't figured out what it does exactly.
For the xilinx PCI, I had to disable it, IIRC.

> > Really no swizzling? That is very unusual, almost everyone needs to set
> > pci_common_swizzle here to make bridges work.
> 
> No generic swizzling, it's done during the bus scan because it's very
> non-standard due to the hardware design.

Well, the swizzling is for the devices behind a bridge. I think your code
will break if you have another PCI-X bridge in a PCI-X slot or a PCIe
switch in a PCIe slot.

I think if you use the correct swizzling function, you not only fix
cards with integrated bridges but also greatly simplify the
pci_realview_pb_map_irq function, which can then become something like:

static int __devinit pci_realview_pb_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
/*	   ^^^^^^ note: it needs to be devinit to support hotplug PCIe. */
{
	switch (slot) {
	case REALVIEW_PCIX_TO_PCI_SLOT: /* logical slot that the PCI bridge connects to */
		return REALVIEW_PCIX_INTA + (((pin - 1) + 3 - (slot & 3)) & 3);
	case REALVIEW_PCIX_TO_PCIE_SLOT:/* logical slot that the PCIe bridge connects to */
		return REALVIEW_PCIE_INTA + (((pin - 1) + 3 - (slot & 3)) & 3);
	}
}

	Arnd

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/6] Realview PCIX support - add main support module code
  2010-10-20 13:02 ` [PATCH 1/6] Realview PCIX support - add main support module code Colin Tuckley
  2010-10-20 21:16   ` Arnd Bergmann
@ 2010-10-28 14:02   ` Russell King - ARM Linux
  1 sibling, 0 replies; 15+ messages in thread
From: Russell King - ARM Linux @ 2010-10-28 14:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 20, 2010 at 02:02:54PM +0100, Colin Tuckley wrote:
> +#include <mach/platform.h>
> +#include <asm/io.h>

linux/io.h

> +static void pcie_fix_sizes(void)
> +{
> +	struct pci_dev *pdev = NULL;
> +	int rrq;
> +	int max_rrq = 4096;
> +
> +	/* Set the max read request size for all devices to the
> +	 * smallest in the tree. So far, the only device we've seen
> +	 * that fails without this is the Marvell Yukon 88E8053 but
> +	 * this may fix other devices too.
> +	 */
> +	while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
> +		rrq = pcie_get_readrq(pdev);
> +		if (rrq > 0 && rrq < max_rrq)
> +			max_rrq = rrq;
> +	}
> +
> +	pdev = NULL;	/* reset scan */
> +	while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
> +		rrq = pcie_get_readrq(pdev);
> +		printk(KERN_DEBUG "%s: %02x:%02x %04x/%04x : RRQSZ %d -> %d\n",
> +				__func__, pdev->bus->number, pdev->devfn,
> +				pdev->vendor, pdev->device, rrq, max_rrq);
> +		pcie_set_readrq(pdev, max_rrq);
> +	}
> +}
> +
> +static int __init realview_pcie_fixups(void)
> +{
> +	pcie_fix_sizes();
> +	return 0;
> +}
> +late_initcall(realview_pcie_fixups);

Shouldn't this be done as a PCI quirk rather than walking the entire list
of PCI devices at some point after drivers have potentially initialised
and bound to these devices?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/6] Realview PCIX support - add main support module code
  2010-10-20 21:16   ` Arnd Bergmann
  2010-10-21 10:03     ` Colin Tuckley
@ 2010-10-28 14:09     ` Russell King - ARM Linux
  2010-10-28 14:29       ` Arnd Bergmann
  1 sibling, 1 reply; 15+ messages in thread
From: Russell King - ARM Linux @ 2010-10-28 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 20, 2010 at 11:16:32PM +0200, Arnd Bergmann wrote:
> > +{
> > +	u32 mode;
> > +	u32 config_addr;
> > +
> > +	writel(0x000307F7, PCIX_UNIT_BASE + PCI_PERRSTAT); /* clear error bit */
> > +	writew(0xfb30, PCIX_UNIT_BASE + PCI_STATUS);	   /* error bit clear */
> 
> I would guess that you need locking here, two drivers might simultaneously be
> accessing config space on different CPUs, or you might have kernel preemption
> enabled and get preempted between the register accesses.

pci config accesses are serialized by a global pci_lock raw spinlock,
which disables IRQs.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/6] Realview PCIX support - add main support module code
  2010-10-28 14:09     ` Russell King - ARM Linux
@ 2010-10-28 14:29       ` Arnd Bergmann
  0 siblings, 0 replies; 15+ messages in thread
From: Arnd Bergmann @ 2010-10-28 14:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 28 October 2010, Russell King - ARM Linux wrote:
> On Wed, Oct 20, 2010 at 11:16:32PM +0200, Arnd Bergmann wrote:
> > > +{
> > > +   u32 mode;
> > > +   u32 config_addr;
> > > +
> > > +   writel(0x000307F7, PCIX_UNIT_BASE + PCI_PERRSTAT); /* clear error bit */
> > > +   writew(0xfb30, PCIX_UNIT_BASE + PCI_STATUS);       /* error bit clear */
> > 
> > I would guess that you need locking here, two drivers might simultaneously be
> > accessing config space on different CPUs, or you might have kernel preemption
> > enabled and get preempted between the register accesses.
> 
> pci config accesses are serialized by a global pci_lock raw spinlock,
> which disables IRQs.

Ok, good. Ignore my comment then.

	Arnd

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2010-10-28 14:29 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-20 13:02 [PATCH 0/6] Add PCI support for ARM RealView boards Colin Tuckley
2010-10-20 13:02 ` [PATCH 1/6] Realview PCIX support - add main support module code Colin Tuckley
2010-10-20 21:16   ` Arnd Bergmann
2010-10-21 10:03     ` Colin Tuckley
2010-10-21 12:44       ` Arnd Bergmann
2010-10-28 14:09     ` Russell King - ARM Linux
2010-10-28 14:29       ` Arnd Bergmann
2010-10-28 14:02   ` Russell King - ARM Linux
2010-10-20 13:02 ` [PATCH 2/6] ARM: enable bridges in pci_common_init Colin Tuckley
2010-10-20 13:03 ` [PATCH 3/6] ARM Realview PCIX map include file changes Colin Tuckley
2010-10-20 21:28   ` Arnd Bergmann
2010-10-20 13:03 ` [PATCH 4/6] ARM Realview PCIX IRQ " Colin Tuckley
2010-10-20 13:03 ` [PATCH 5/6] ARM Realview PCIX board " Colin Tuckley
2010-10-20 13:03 ` [PATCH 6/6] ARM Realview PCIX build " Colin Tuckley
2010-10-20 21:32   ` Arnd Bergmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).