Orion: enable access to local config space

This patch enables access to the local PCIe/PCI configuration
space, and is necessary for such things as PCI Advanced Error
Recovery to work.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Reviewed-by: Tzachi Perelstein <tzachi@marvell.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Nicolas Pitre <nico@marvell.com>
This commit is contained in:
Lennert Buytenhek 2008-03-27 14:51:41 -04:00 committed by Nicolas Pitre
parent a99842704a
commit d50c60a87a

View file

@ -50,15 +50,18 @@ static int pcie_valid_config(int bus, int dev)
{ {
/* /*
* Don't go out when trying to access -- * Don't go out when trying to access --
* 1. our own device / nonexisting device on local bus * 1. nonexisting device on local bus
* 2. where there's no device connected (no link) * 2. where there's no device connected (no link)
*/ */
if (bus == 0 && dev != 1) if (bus == 0 && dev == 0)
return 0; return 1;
if (!orion_pcie_link_up(PCIE_BASE)) if (!orion_pcie_link_up(PCIE_BASE))
return 0; return 0;
if (bus == 0 && dev != 1)
return 0;
return 1; return 1;
} }
@ -272,12 +275,6 @@ int orion_pci_local_bus_nr(void)
return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS); return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
} }
static int orion_pci_local_dev_nr(void)
{
u32 conf = orion_read(PCI_P2P_CONF);
return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS);
}
static int orion_pci_hw_rd_conf(int bus, int dev, u32 func, static int orion_pci_hw_rd_conf(int bus, int dev, u32 func,
u32 where, u32 size, u32 *val) u32 where, u32 size, u32 *val)
{ {
@ -333,8 +330,8 @@ static int orion_pci_rd_conf(struct pci_bus *bus, u32 devfn,
/* /*
* Don't go out for local device * Don't go out for local device
*/ */
if ((orion_pci_local_bus_nr() == bus->number) && if (bus->number == orion_pci_local_bus_nr() &&
(orion_pci_local_dev_nr() == PCI_SLOT(devfn))) { PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0) {
*val = 0xffffffff; *val = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
} }
@ -346,11 +343,8 @@ static int orion_pci_rd_conf(struct pci_bus *bus, u32 devfn,
static int orion_pci_wr_conf(struct pci_bus *bus, u32 devfn, static int orion_pci_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val) int where, int size, u32 val)
{ {
/* if (bus->number == orion_pci_local_bus_nr() &&
* Don't go out for local device PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0)
*/
if ((orion_pci_local_bus_nr() == bus->number) &&
(orion_pci_local_dev_nr() == PCI_SLOT(devfn)))
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
return orion_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn), return orion_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn),
@ -389,23 +383,21 @@ static void __init orion_pci_set_bus_nr(int nr)
static void __init orion_pci_master_slave_enable(void) static void __init orion_pci_master_slave_enable(void)
{ {
int bus_nr, dev_nr, func, reg; int bus_nr, func, reg;
u32 val; u32 val;
bus_nr = orion_pci_local_bus_nr(); bus_nr = orion_pci_local_bus_nr();
dev_nr = orion_pci_local_dev_nr();
func = PCI_CONF_FUNC_STAT_CMD; func = PCI_CONF_FUNC_STAT_CMD;
reg = PCI_CONF_REG_STAT_CMD; reg = PCI_CONF_REG_STAT_CMD;
orion_pci_hw_rd_conf(bus_nr, dev_nr, func, reg, 4, &val); orion_pci_hw_rd_conf(bus_nr, 0, func, reg, 4, &val);
val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7); orion_pci_hw_wr_conf(bus_nr, 0, func, reg, 4, val | 0x7);
} }
static void __init orion_setup_pci_wins(struct mbus_dram_target_info *dram) static void __init orion_setup_pci_wins(struct mbus_dram_target_info *dram)
{ {
u32 win_enable; u32 win_enable;
int bus; int bus;
int dev;
int i; int i;
/* /*
@ -418,7 +410,6 @@ static void __init orion_setup_pci_wins(struct mbus_dram_target_info *dram)
* Setup windows for DDR banks. * Setup windows for DDR banks.
*/ */
bus = orion_pci_local_bus_nr(); bus = orion_pci_local_bus_nr();
dev = orion_pci_local_dev_nr();
for (i = 0; i < dram->num_cs; i++) { for (i = 0; i < dram->num_cs; i++) {
struct mbus_dram_window *cs = dram->cs + i; struct mbus_dram_window *cs = dram->cs + i;
@ -430,15 +421,15 @@ static void __init orion_setup_pci_wins(struct mbus_dram_target_info *dram)
* Write DRAM bank base address register. * Write DRAM bank base address register.
*/ */
reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index); reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index);
orion_pci_hw_rd_conf(bus, dev, func, reg, 4, &val); orion_pci_hw_rd_conf(bus, 0, func, reg, 4, &val);
val = (cs->base & 0xfffff000) | (val & 0xfff); val = (cs->base & 0xfffff000) | (val & 0xfff);
orion_pci_hw_wr_conf(bus, dev, func, reg, 4, val); orion_pci_hw_wr_conf(bus, 0, func, reg, 4, val);
/* /*
* Write DRAM bank size register. * Write DRAM bank size register.
*/ */
reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index); reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index);
orion_pci_hw_wr_conf(bus, dev, func, reg, 4, 0); orion_pci_hw_wr_conf(bus, 0, func, reg, 4, 0);
orion_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index), orion_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index),
(cs->size - 1) & 0xfffff000); (cs->size - 1) & 0xfffff000);
orion_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index), orion_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index),
@ -519,6 +510,23 @@ static int __init pci_setup(struct pci_sys_data *sys)
/***************************************************************************** /*****************************************************************************
* General PCIE + PCI * General PCIE + PCI
****************************************************************************/ ****************************************************************************/
static void __devinit rc_pci_fixup(struct pci_dev *dev)
{
/*
* Prevent enumeration of root complex.
*/
if (dev->bus->parent == NULL && dev->devfn == 0) {
int i;
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
dev->resource[i].start = 0;
dev->resource[i].end = 0;
dev->resource[i].flags = 0;
}
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
int __init orion_pci_sys_setup(int nr, struct pci_sys_data *sys) int __init orion_pci_sys_setup(int nr, struct pci_sys_data *sys)
{ {
int ret = 0; int ret = 0;