diff options
-rw-r--r-- | Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt | 42 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 20 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 3 |
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 | ||
28 | Optional 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 | |||
28 | Example: | 38 | Example: |
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 | |||
55 | The Freescale hypervisor and msi-address-64 | ||
56 | ------------------------------------------- | ||
57 | Normally, PCI devices have access to all of CCSR via an ATMU mapping. The | ||
58 | Freescale MSI driver calculates the address of MSIIR (in the MSI register | ||
59 | block) and sets that address as the MSI message address. | ||
60 | |||
61 | In a virtualized environment, the hypervisor may need to create an IOMMU | ||
62 | mapping for MSIIR. The Freescale ePAPR hypervisor has this requirement | ||
63 | because of hardware limitations of the Peripheral Access Management Unit | ||
64 | (PAMU), which is currently the only IOMMU that the hypervisor supports. | ||
65 | The ATMU is programmed with the guest physical address, and the PAMU | ||
66 | intercepts transactions and reroutes them to the true physical address. | ||
67 | |||
68 | In the PAMU, each PCI controller is given only one primary window. The | ||
69 | PAMU restricts DMA operations so that they can only occur within a window. | ||
70 | Because PCI devices must be able to DMA to memory, the primary window must | ||
71 | be used to cover all of the guest's memory space. | ||
72 | |||
73 | PAMU primary windows can be divided into 256 subwindows, and each | ||
74 | subwindow can have its own address mapping ("guest physical" to "true | ||
75 | physical"). However, each subwindow has to have the same alignment, which | ||
76 | means they cannot be located at just any address. Because of these | ||
77 | restrictions, it is usually impossible to create a 4KB subwindow that | ||
78 | covers MSIIR where it's normally located. | ||
79 | |||
80 | Therefore, the hypervisor has to create a subwindow inside the same | ||
81 | primary window used for memory, but mapped to the MSIR block (where MSIIR | ||
82 | lives). The first subwindow after the end of guest memory is used for | ||
83 | this. The address specified in the msi-address-64 property is the PCI | ||
84 | address of MSIIR. The hypervisor configures the PAMU to map that address to | ||
85 | the 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 | ||
31 | struct fsl_msi_feature { | 31 | struct 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 | ||
36 | struct fsl_msi_cascade_data { | 36 | struct 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]; |