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

Commit 7160266a authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/host-mvebu' into next

* pci/host-mvebu:
  PCI: mvebu: Remove duplicate of_clk_get_by_name() call
  PCI: mvebu: Support a bridge with no IO port window
  PCI: mvebu: Obey bridge PCI_COMMAND_MEM and PCI_COMMAND_IO bits
  PCI: mvebu: Drop writes to bridge Secondary Status register
parents ed00f97d 84f47190
Loading
Loading
Loading
Loading
+55 −31
Original line number Diff line number Diff line
@@ -150,6 +150,11 @@ static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg)
	return readl(port->base + reg);
}

static inline bool mvebu_has_ioport(struct mvebu_pcie_port *port)
{
	return port->io_target != -1 && port->io_attr != -1;
}

static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)
{
	return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
@@ -300,7 +305,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)

	/* Are the new iobase/iolimit values invalid? */
	if (port->bridge.iolimit < port->bridge.iobase ||
	    port->bridge.iolimitupper < port->bridge.iobaseupper) {
	    port->bridge.iolimitupper < port->bridge.iobaseupper ||
	    !(port->bridge.command & PCI_COMMAND_IO)) {

		/* If a window was configured, remove it */
		if (port->iowin_base) {
@@ -313,6 +319,12 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
		return;
	}

	if (!mvebu_has_ioport(port)) {
		dev_WARN(&port->pcie->pdev->dev,
			 "Attempt to set IO when IO is disabled\n");
		return;
	}

	/*
	 * We read the PCI-to-PCI bridge emulated registers, and
	 * calculate the base address and size of the address decoding
@@ -337,7 +349,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
{
	/* Are the new membase/memlimit values invalid? */
	if (port->bridge.memlimit < port->bridge.membase) {
	if (port->bridge.memlimit < port->bridge.membase ||
	    !(port->bridge.command & PCI_COMMAND_MEMORY)) {

		/* If a window was configured, remove it */
		if (port->memwin_base) {
@@ -426,6 +439,9 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
		break;

	case PCI_IO_BASE:
		if (!mvebu_has_ioport(port))
			*value = bridge->secondary_status << 16;
		else
			*value = (bridge->secondary_status << 16 |
				  bridge->iolimit          <<  8 |
				  bridge->iobase);
@@ -490,8 +506,19 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,

	switch (where & ~3) {
	case PCI_COMMAND:
	{
		u32 old = bridge->command;

		if (!mvebu_has_ioport(port))
			value &= ~PCI_COMMAND_IO;

		bridge->command = value & 0xffff;
		if ((old ^ bridge->command) & PCI_COMMAND_IO)
			mvebu_pcie_handle_iobase_change(port);
		if ((old ^ bridge->command) & PCI_COMMAND_MEMORY)
			mvebu_pcie_handle_membase_change(port);
		break;
	}

	case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
		bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value;
@@ -505,7 +532,6 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
		 */
		bridge->iobase = (value & 0xff) | PCI_IO_RANGE_TYPE_32;
		bridge->iolimit = ((value >> 8) & 0xff) | PCI_IO_RANGE_TYPE_32;
		bridge->secondary_status = value >> 16;
		mvebu_pcie_handle_iobase_change(port);
		break;

@@ -656,7 +682,9 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
	struct mvebu_pcie *pcie = sys_to_pcie(sys);
	int i;

	pci_add_resource_offset(&sys->resources, &pcie->realio, sys->io_offset);
	if (resource_size(&pcie->realio) != 0)
		pci_add_resource_offset(&sys->resources, &pcie->realio,
					sys->io_offset);
	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
	pci_add_resource(&sys->resources, &pcie->busn);

@@ -757,12 +785,17 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,
#define DT_CPUADDR_TO_ATTR(cpuaddr)   (((cpuaddr) >> 48) & 0xFF)

static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
			      unsigned long type, int *tgt, int *attr)
			      unsigned long type,
			      unsigned int *tgt,
			      unsigned int *attr)
{
	const int na = 3, ns = 2;
	const __be32 *range;
	int rlen, nranges, rangesz, pna, i;

	*tgt = -1;
	*attr = -1;

	range = of_get_property(np, "ranges", &rlen);
	if (!range)
		return -EINVAL;
@@ -832,16 +865,15 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
	}

	mvebu_mbus_get_pcie_io_aperture(&pcie->io);
	if (resource_size(&pcie->io) == 0) {
		dev_err(&pdev->dev, "invalid I/O aperture size\n");
		return -EINVAL;
	}

	if (resource_size(&pcie->io) != 0) {
		pcie->realio.flags = pcie->io.flags;
		pcie->realio.start = PCIBIOS_MIN_IO;
		pcie->realio.end = min_t(resource_size_t,
					 IO_SPACE_LIMIT,
					 resource_size(&pcie->io));
	} else
		pcie->realio = pcie->io;

	/* Get the bus range */
	ret = of_pci_parse_bus_range(np, &pcie->busn);
@@ -900,12 +932,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
			continue;
		}

		ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO,
		if (resource_size(&pcie->io) != 0)
			mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO,
					   &port->io_target, &port->io_attr);
		if (ret < 0) {
			dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n",
				port->port, port->lane);
			continue;
		else {
			port->io_target = -1;
			port->io_attr = -1;
		}

		port->reset_gpio = of_get_named_gpio_flags(child,
@@ -954,14 +986,6 @@ static int mvebu_pcie_probe(struct platform_device *pdev)

		mvebu_pcie_set_local_dev_nr(port, 1);

		port->clk = of_clk_get_by_name(child, NULL);
		if (IS_ERR(port->clk)) {
			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
			       port->port, port->lane);
			iounmap(port->base);
			continue;
		}

		port->dn = child;
		spin_lock_init(&port->conf_lock);
		mvebu_sw_pci_bridge_init(port);