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

Commit 5b4deb65 authored by Thomas Petazzoni's avatar Thomas Petazzoni Committed by Jason Cooper
Browse files

PCI: mvebu: add support for MSI



This commit adds support for Message Signaled Interrupts in the
Marvell PCIe host controller. The work is very simple: it simply gets
a reference to the msi_chip associated to the PCIe controller thanks
to the msi-parent DT property, and stores this reference in the
pci_bus structure. This is enough to let the Linux PCI core use the
functions of msi_chip to setup and teardown MSIs.

Signed-off-by: default avatarThomas Petazzoni <thomas.petazzoni@free-electrons.com>
Reviewed-by: default avatarThierry Reding <thierry.reding@gmail.com>
Acked-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Signed-off-by: default avatarJason Cooper <jason@lakedaemon.net>
parent 31f614ed
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@ Mandatory properties:
- ranges: ranges describing the MMIO registers to control the PCIe
  interfaces, and ranges describing the MBus windows needed to access
  the memory and I/O regions of each PCIe interface.
- msi-parent: Link to the hardware entity that serves as the Message
  Signaled Interrupt controller for this PCI controller.

The ranges describing the MMIO registers have the following layout:

@@ -86,6 +88,7 @@ pcie-controller {
	#size-cells = <2>;

	bus-range = <0x00 0xff>;
	msi-parent = <&mpic>;

	ranges =
	       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000	/* Port 0.0 registers */
+26 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/mbus.h>
#include <linux/msi.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/of_address.h>
@@ -103,6 +104,7 @@ struct mvebu_pcie_port;
struct mvebu_pcie {
	struct platform_device *pdev;
	struct mvebu_pcie_port *ports;
	struct msi_chip *msi;
	struct resource io;
	struct resource realio;
	struct resource mem;
@@ -673,6 +675,12 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
	return bus;
}

void mvebu_pcie_add_bus(struct pci_bus *bus)
{
	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
	bus->msi = pcie->msi;
}

resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
					  const struct resource *res,
					  resource_size_t start,
@@ -709,6 +717,7 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)
	hw.map_irq        = mvebu_pcie_map_irq;
	hw.ops            = &mvebu_pcie_ops;
	hw.align_resource = mvebu_pcie_align_resource;
	hw.add_bus        = mvebu_pcie_add_bus;

	pci_common_init(&hw);
}
@@ -777,6 +786,21 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
	return -ENOENT;
}

static void __init mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
{
	struct device_node *msi_node;

	msi_node = of_parse_phandle(pcie->pdev->dev.of_node,
				    "msi-parent", 0);
	if (!msi_node)
		return;

	pcie->msi = of_pci_find_msi_chip_by_node(msi_node);

	if (pcie->msi)
		pcie->msi->dev = &pcie->pdev->dev;
}

static int __init mvebu_pcie_probe(struct platform_device *pdev)
{
	struct mvebu_pcie *pcie;
@@ -912,6 +936,8 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
		i++;
	}

	mvebu_pcie_msi_enable(pcie);

	mvebu_pcie_enable(pcie);

	return 0;