Patchwork sparc,leon: fix GRPCI2 device0 PCI config space access

login
register
mail settings
Submitter Daniel Hellstrom
Date Feb. 28, 2013, 2:31 p.m.
Message ID <1362061915-634-1-git-send-email-daniel@gaisler.com>
Download mbox | patch
Permalink /patch/223970/
State Accepted
Delegated to: David Miller
Headers show

Comments

Daniel Hellstrom - Feb. 28, 2013, 2:31 p.m.
bus=0 slot=0 (device0) was used internally by the PCI host driver
to access the PCI host controller itself, however that had the
effect that PCI device0 was never accessible, which is wrong
when the motherboard has connected PCI AD16 signal to a slot.
A special case for accessing the PCI host controller itself is
added with this patch, by setting bus to TGT.

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 arch/sparc/kernel/leon_pci_grpci2.c |   41 ++++++++++++++++++++++------------
 1 files changed, 26 insertions(+), 15 deletions(-)
David Miller - March 3, 2013, 6:36 a.m.
From: Daniel Hellstrom <daniel@gaisler.com>
Date: Thu, 28 Feb 2013 15:31:55 +0100

> bus=0 slot=0 (device0) was used internally by the PCI host driver
> to access the PCI host controller itself, however that had the
> effect that PCI device0 was never accessible, which is wrong
> when the motherboard has connected PCI AD16 signal to a slot.
> A special case for accessing the PCI host controller itself is
> added with this patch, by setting bus to TGT.
> 
> Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>

Applied, thanks.
--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c
index 40fdcbc..5f0402a 100644
--- a/arch/sparc/kernel/leon_pci_grpci2.c
+++ b/arch/sparc/kernel/leon_pci_grpci2.c
@@ -186,6 +186,8 @@  struct grpci2_cap_first {
 #define CAP9_IOMAP_OFS 0x20
 #define CAP9_BARSIZE_OFS 0x24
 
+#define TGT 256
+
 struct grpci2_priv {
 	struct leon_pci_info	info; /* must be on top of this structure */
 	struct grpci2_regs	*regs;
@@ -237,8 +239,12 @@  static int grpci2_cfg_r32(struct grpci2_priv *priv, unsigned int bus,
 	if (where & 0x3)
 		return -EINVAL;
 
-	if (bus == 0 && PCI_SLOT(devfn) != 0)
-		devfn += (0x8 * 6);
+	if (bus == 0) {
+		devfn += (0x8 * 6); /* start at AD16=Device0 */
+	} else if (bus == TGT) {
+		bus = 0;
+		devfn = 0; /* special case: bridge controller itself */
+	}
 
 	/* Select bus */
 	spin_lock_irqsave(&grpci2_dev_lock, flags);
@@ -303,8 +309,12 @@  static int grpci2_cfg_w32(struct grpci2_priv *priv, unsigned int bus,
 	if (where & 0x3)
 		return -EINVAL;
 
-	if (bus == 0 && PCI_SLOT(devfn) != 0)
-		devfn += (0x8 * 6);
+	if (bus == 0) {
+		devfn += (0x8 * 6); /* start at AD16=Device0 */
+	} else if (bus == TGT) {
+		bus = 0;
+		devfn = 0; /* special case: bridge controller itself */
+	}
 
 	/* Select bus */
 	spin_lock_irqsave(&grpci2_dev_lock, flags);
@@ -368,7 +378,7 @@  static int grpci2_read_config(struct pci_bus *bus, unsigned int devfn,
 	unsigned int busno = bus->number;
 	int ret;
 
-	if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) {
+	if (PCI_SLOT(devfn) > 15 || busno > 255) {
 		*val = ~0;
 		return 0;
 	}
@@ -406,7 +416,7 @@  static int grpci2_write_config(struct pci_bus *bus, unsigned int devfn,
 	struct grpci2_priv *priv = grpci2priv;
 	unsigned int busno = bus->number;
 
-	if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0))
+	if (PCI_SLOT(devfn) > 15 || busno > 255)
 		return 0;
 
 #ifdef GRPCI2_DEBUG_CFGACCESS
@@ -578,15 +588,15 @@  void grpci2_hw_init(struct grpci2_priv *priv)
 		REGSTORE(regs->ahbmst_map[i], priv->pci_area);
 
 	/* Get the GRPCI2 Host PCI ID */
-	grpci2_cfg_r32(priv, 0, 0, PCI_VENDOR_ID, &priv->pciid);
+	grpci2_cfg_r32(priv, TGT, 0, PCI_VENDOR_ID, &priv->pciid);
 
 	/* Get address to first (always defined) capability structure */
-	grpci2_cfg_r8(priv, 0, 0, PCI_CAPABILITY_LIST, &capptr);
+	grpci2_cfg_r8(priv, TGT, 0, PCI_CAPABILITY_LIST, &capptr);
 
 	/* Enable/Disable Byte twisting */
-	grpci2_cfg_r32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, &io_map);
+	grpci2_cfg_r32(priv, TGT, 0, capptr+CAP9_IOMAP_OFS, &io_map);
 	io_map = (io_map & ~0x1) | (priv->bt_enabled ? 1 : 0);
-	grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, io_map);
+	grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_IOMAP_OFS, io_map);
 
 	/* Setup the Host's PCI Target BARs for other peripherals to access,
 	 * and do DMA to the host's memory. The target BARs can be sized and
@@ -617,17 +627,18 @@  void grpci2_hw_init(struct grpci2_priv *priv)
 				pciadr = 0;
 			}
 		}
-		grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BARSIZE_OFS+i*4, bar_sz);
-		grpci2_cfg_w32(priv, 0, 0, PCI_BASE_ADDRESS_0+i*4, pciadr);
-		grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr);
+		grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_BARSIZE_OFS+i*4,
+				bar_sz);
+		grpci2_cfg_w32(priv, TGT, 0, PCI_BASE_ADDRESS_0+i*4, pciadr);
+		grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr);
 		printk(KERN_INFO "        TGT BAR[%d]: 0x%08x (PCI)-> 0x%08x\n",
 			i, pciadr, ahbadr);
 	}
 
 	/* set as bus master and enable pci memory responses */
-	grpci2_cfg_r32(priv, 0, 0, PCI_COMMAND, &data);
+	grpci2_cfg_r32(priv, TGT, 0, PCI_COMMAND, &data);
 	data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-	grpci2_cfg_w32(priv, 0, 0, PCI_COMMAND, data);
+	grpci2_cfg_w32(priv, TGT, 0, PCI_COMMAND, data);
 
 	/* Enable Error respone (CPU-TRAP) on illegal memory access. */
 	REGSTORE(regs->ctrl, CTRL_ER | CTRL_PE);