- device_type, set to "pci"
- ranges: ranges for the PCI memory and I/O regions, as well as the
MMIO registers to control the PCIe interfaces.
+- msi-parent: Link to the hardware entity that serves as the Message
+ Signaled Interrupt controller for this PCI controller.
In addition, the Device Tree node must have sub-nodes describing each
PCIe interface, having the following mandatory properties:
#size-cells = <2>;
bus-range = <0x00 0xff>;
+ msi-parent = <&mpic>;
ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000 /* Port 0.0 registers */
0x82000000 0 0xd0042000 0xd0042000 0 0x00002000 /* Port 2.0 registers */
#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>
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;
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,
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);
}
return devm_request_and_ioremap(&pdev->dev, ®s);
}
+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;
i++;
}
+ mvebu_pcie_msi_enable(pcie);
+
mvebu_pcie_enable(pcie);
return 0;