Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d50c60a8 authored by Lennert Buytenhek's avatar Lennert Buytenhek Committed by Nicolas Pitre
Browse files

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: default avatarLennert Buytenhek <buytenh@marvell.com>
Reviewed-by: default avatarTzachi Perelstein <tzachi@marvell.com>
Acked-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarNicolas Pitre <nico@marvell.com>
parent a9984270
Loading
Loading
Loading
Loading
+33 −25
Original line number Original line Diff line number Diff line
@@ -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;