Commit a2956428 authored by Daniel Hellstrom's avatar Daniel Hellstrom Committed by David S. Miller

sparc,leon: fix GRPCI2 device0 PCI config space access

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: default avatarDaniel Hellstrom <daniel@gaisler.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cb29529e
...@@ -186,6 +186,8 @@ struct grpci2_cap_first { ...@@ -186,6 +186,8 @@ struct grpci2_cap_first {
#define CAP9_IOMAP_OFS 0x20 #define CAP9_IOMAP_OFS 0x20
#define CAP9_BARSIZE_OFS 0x24 #define CAP9_BARSIZE_OFS 0x24
#define TGT 256
struct grpci2_priv { struct grpci2_priv {
struct leon_pci_info info; /* must be on top of this structure */ struct leon_pci_info info; /* must be on top of this structure */
struct grpci2_regs *regs; struct grpci2_regs *regs;
...@@ -237,8 +239,12 @@ static int grpci2_cfg_r32(struct grpci2_priv *priv, unsigned int bus, ...@@ -237,8 +239,12 @@ static int grpci2_cfg_r32(struct grpci2_priv *priv, unsigned int bus,
if (where & 0x3) if (where & 0x3)
return -EINVAL; return -EINVAL;
if (bus == 0 && PCI_SLOT(devfn) != 0) if (bus == 0) {
devfn += (0x8 * 6); devfn += (0x8 * 6); /* start at AD16=Device0 */
} else if (bus == TGT) {
bus = 0;
devfn = 0; /* special case: bridge controller itself */
}
/* Select bus */ /* Select bus */
spin_lock_irqsave(&grpci2_dev_lock, flags); spin_lock_irqsave(&grpci2_dev_lock, flags);
...@@ -303,8 +309,12 @@ static int grpci2_cfg_w32(struct grpci2_priv *priv, unsigned int bus, ...@@ -303,8 +309,12 @@ static int grpci2_cfg_w32(struct grpci2_priv *priv, unsigned int bus,
if (where & 0x3) if (where & 0x3)
return -EINVAL; return -EINVAL;
if (bus == 0 && PCI_SLOT(devfn) != 0) if (bus == 0) {
devfn += (0x8 * 6); devfn += (0x8 * 6); /* start at AD16=Device0 */
} else if (bus == TGT) {
bus = 0;
devfn = 0; /* special case: bridge controller itself */
}
/* Select bus */ /* Select bus */
spin_lock_irqsave(&grpci2_dev_lock, flags); spin_lock_irqsave(&grpci2_dev_lock, flags);
...@@ -368,7 +378,7 @@ static int grpci2_read_config(struct pci_bus *bus, unsigned int devfn, ...@@ -368,7 +378,7 @@ static int grpci2_read_config(struct pci_bus *bus, unsigned int devfn,
unsigned int busno = bus->number; unsigned int busno = bus->number;
int ret; int ret;
if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) { if (PCI_SLOT(devfn) > 15 || busno > 255) {
*val = ~0; *val = ~0;
return 0; return 0;
} }
...@@ -406,7 +416,7 @@ static int grpci2_write_config(struct pci_bus *bus, unsigned int devfn, ...@@ -406,7 +416,7 @@ static int grpci2_write_config(struct pci_bus *bus, unsigned int devfn,
struct grpci2_priv *priv = grpci2priv; struct grpci2_priv *priv = grpci2priv;
unsigned int busno = bus->number; 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; return 0;
#ifdef GRPCI2_DEBUG_CFGACCESS #ifdef GRPCI2_DEBUG_CFGACCESS
...@@ -578,15 +588,15 @@ void grpci2_hw_init(struct grpci2_priv *priv) ...@@ -578,15 +588,15 @@ void grpci2_hw_init(struct grpci2_priv *priv)
REGSTORE(regs->ahbmst_map[i], priv->pci_area); REGSTORE(regs->ahbmst_map[i], priv->pci_area);
/* Get the GRPCI2 Host PCI ID */ /* 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 */ /* 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 */ /* 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); 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, /* 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 * 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) ...@@ -617,17 +627,18 @@ void grpci2_hw_init(struct grpci2_priv *priv)
pciadr = 0; pciadr = 0;
} }
} }
grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BARSIZE_OFS+i*4, bar_sz); grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_BARSIZE_OFS+i*4,
grpci2_cfg_w32(priv, 0, 0, PCI_BASE_ADDRESS_0+i*4, pciadr); bar_sz);
grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr); 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", printk(KERN_INFO " TGT BAR[%d]: 0x%08x (PCI)-> 0x%08x\n",
i, pciadr, ahbadr); i, pciadr, ahbadr);
} }
/* set as bus master and enable pci memory responses */ /* 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); 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. */ /* Enable Error respone (CPU-TRAP) on illegal memory access. */
REGSTORE(regs->ctrl, CTRL_ER | CTRL_PE); REGSTORE(regs->ctrl, CTRL_ER | CTRL_PE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment