aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt42
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c20
-rw-r--r--arch/powerpc/sysdev/fsl_msi.h3
3 files changed, 57 insertions, 8 deletions
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
index 70558c3f3682..5d586e1ccaf5 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
@@ -25,6 +25,16 @@ Required properties:
25 are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed 25 are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
26 to MPIC. 26 to MPIC.
27 27
28Optional properties:
29- msi-address-64: 64-bit PCI address of the MSIIR register. The MSIIR register
30 is used for MSI messaging. The address of MSIIR in PCI address space is
31 the MSI message address.
32
33 This property may be used in virtualized environments where the hypervisor
34 has created an alternate mapping for the MSIR block. See below for an
35 explanation.
36
37
28Example: 38Example:
29 msi@41600 { 39 msi@41600 {
30 compatible = "fsl,mpc8610-msi", "fsl,mpic-msi"; 40 compatible = "fsl,mpc8610-msi", "fsl,mpic-msi";
@@ -41,3 +51,35 @@ Example:
41 0xe7 0>; 51 0xe7 0>;
42 interrupt-parent = <&mpic>; 52 interrupt-parent = <&mpic>;
43 }; 53 };
54
55The Freescale hypervisor and msi-address-64
56-------------------------------------------
57Normally, PCI devices have access to all of CCSR via an ATMU mapping. The
58Freescale MSI driver calculates the address of MSIIR (in the MSI register
59block) and sets that address as the MSI message address.
60
61In a virtualized environment, the hypervisor may need to create an IOMMU
62mapping for MSIIR. The Freescale ePAPR hypervisor has this requirement
63because of hardware limitations of the Peripheral Access Management Unit
64(PAMU), which is currently the only IOMMU that the hypervisor supports.
65The ATMU is programmed with the guest physical address, and the PAMU
66intercepts transactions and reroutes them to the true physical address.
67
68In the PAMU, each PCI controller is given only one primary window. The
69PAMU restricts DMA operations so that they can only occur within a window.
70Because PCI devices must be able to DMA to memory, the primary window must
71be used to cover all of the guest's memory space.
72
73PAMU primary windows can be divided into 256 subwindows, and each
74subwindow can have its own address mapping ("guest physical" to "true
75physical"). However, each subwindow has to have the same alignment, which
76means they cannot be located at just any address. Because of these
77restrictions, it is usually impossible to create a 4KB subwindow that
78covers MSIIR where it's normally located.
79
80Therefore, the hypervisor has to create a subwindow inside the same
81primary window used for memory, but mapped to the MSIR block (where MSIIR
82lives). The first subwindow after the end of guest memory is used for
83this. The address specified in the msi-address-64 property is the PCI
84address of MSIIR. The hypervisor configures the PAMU to map that address to
85the true physical address of MSIIR.
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 1cca25146b1f..e5c344d336ea 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -30,7 +30,7 @@ LIST_HEAD(msi_head);
30 30
31struct fsl_msi_feature { 31struct fsl_msi_feature {
32 u32 fsl_pic_ip; 32 u32 fsl_pic_ip;
33 u32 msiir_offset; 33 u32 msiir_offset; /* Offset of MSIIR, relative to start of MSIR bank */
34}; 34};
35 35
36struct fsl_msi_cascade_data { 36struct fsl_msi_cascade_data {
@@ -126,10 +126,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
126{ 126{
127 struct fsl_msi *msi_data = fsl_msi_data; 127 struct fsl_msi *msi_data = fsl_msi_data;
128 struct pci_controller *hose = pci_bus_to_host(pdev->bus); 128 struct pci_controller *hose = pci_bus_to_host(pdev->bus);
129 u64 base = fsl_pci_immrbar_base(hose); 129 u64 address; /* Physical address of the MSIIR */
130 int len;
131 const u64 *reg;
132
133 /* If the msi-address-64 property exists, then use it */
134 reg = of_get_property(hose->dn, "msi-address-64", &len);
135 if (reg && (len == sizeof(u64)))
136 address = be64_to_cpup(reg);
137 else
138 address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset;
130 139
131 msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base); 140 msg->address_lo = lower_32_bits(address);
132 msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base); 141 msg->address_hi = upper_32_bits(address);
133 142
134 msg->data = hwirq; 143 msg->data = hwirq;
135 144
@@ -359,8 +368,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
359 368
360 msi->irqhost->host_data = msi; 369 msi->irqhost->host_data = msi;
361 370
362 msi->msi_addr_hi = 0x0; 371 msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff);
363 msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff);
364 372
365 rc = fsl_msi_init_allocator(msi); 373 rc = fsl_msi_init_allocator(msi);
366 if (rc) { 374 if (rc) {
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h
index 624580c252d7..1313abbc5200 100644
--- a/arch/powerpc/sysdev/fsl_msi.h
+++ b/arch/powerpc/sysdev/fsl_msi.h
@@ -28,8 +28,7 @@ struct fsl_msi {
28 28
29 unsigned long cascade_irq; 29 unsigned long cascade_irq;
30 30
31 u32 msi_addr_lo; 31 u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */
32 u32 msi_addr_hi;
33 void __iomem *msi_regs; 32 void __iomem *msi_regs;
34 u32 feature; 33 u32 feature;
35 int msi_virqs[NR_MSI_REG]; 34 int msi_virqs[NR_MSI_REG];