aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-05-09 22:58:24 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-05-09 22:58:24 -0400
commitb48d441a8ab8a89bd32a3a981a05b8a26905dfc7 (patch)
tree09faed1b557b70f439064d3baaefef91e0ee7334 /arch/powerpc/sysdev
parenta7243c1d09ade57d8d48a350753dc2d1af735805 (diff)
parentdce4c92d69db53ed0e09191428f17ac9a14ad248 (diff)
Merge remote-tracking branch 'jwb/next' into next
Josh writes: << A few patches from Suzie for 47x kexec/kdump support, and some MSI patches from Mai La. >>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/ppc4xx_msi.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
index 1c2d7af17bbe..82c6702dcbab 100644
--- a/arch/powerpc/sysdev/ppc4xx_msi.c
+++ b/arch/powerpc/sysdev/ppc4xx_msi.c
@@ -28,10 +28,11 @@
28#include <linux/of_platform.h> 28#include <linux/of_platform.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/export.h> 30#include <linux/export.h>
31#include <linux/kernel.h>
31#include <asm/prom.h> 32#include <asm/prom.h>
32#include <asm/hw_irq.h> 33#include <asm/hw_irq.h>
33#include <asm/ppc-pci.h> 34#include <asm/ppc-pci.h>
34#include <boot/dcr.h> 35#include <asm/dcr.h>
35#include <asm/dcr-regs.h> 36#include <asm/dcr-regs.h>
36#include <asm/msi_bitmap.h> 37#include <asm/msi_bitmap.h>
37 38
@@ -43,13 +44,14 @@
43#define PEIH_FLUSH0 0x30 44#define PEIH_FLUSH0 0x30
44#define PEIH_FLUSH1 0x38 45#define PEIH_FLUSH1 0x38
45#define PEIH_CNTRST 0x48 46#define PEIH_CNTRST 0x48
46#define NR_MSI_IRQS 4 47
48static int msi_irqs;
47 49
48struct ppc4xx_msi { 50struct ppc4xx_msi {
49 u32 msi_addr_lo; 51 u32 msi_addr_lo;
50 u32 msi_addr_hi; 52 u32 msi_addr_hi;
51 void __iomem *msi_regs; 53 void __iomem *msi_regs;
52 int msi_virqs[NR_MSI_IRQS]; 54 int *msi_virqs;
53 struct msi_bitmap bitmap; 55 struct msi_bitmap bitmap;
54 struct device_node *msi_dev; 56 struct device_node *msi_dev;
55}; 57};
@@ -61,7 +63,7 @@ static int ppc4xx_msi_init_allocator(struct platform_device *dev,
61{ 63{
62 int err; 64 int err;
63 65
64 err = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, 66 err = msi_bitmap_alloc(&msi_data->bitmap, msi_irqs,
65 dev->dev.of_node); 67 dev->dev.of_node);
66 if (err) 68 if (err)
67 return err; 69 return err;
@@ -83,6 +85,11 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
83 struct msi_desc *entry; 85 struct msi_desc *entry;
84 struct ppc4xx_msi *msi_data = &ppc4xx_msi; 86 struct ppc4xx_msi *msi_data = &ppc4xx_msi;
85 87
88 msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int),
89 GFP_KERNEL);
90 if (!msi_data->msi_virqs)
91 return -ENOMEM;
92
86 list_for_each_entry(entry, &dev->msi_list, list) { 93 list_for_each_entry(entry, &dev->msi_list, list) {
87 int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); 94 int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
88 if (int_no >= 0) 95 if (int_no >= 0)
@@ -150,12 +157,11 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
150 if (!sdr_addr) 157 if (!sdr_addr)
151 return -1; 158 return -1;
152 159
153 SDR0_WRITE(sdr_addr, (u64)res.start >> 32); /*HIGH addr */ 160 mtdcri(SDR0, *sdr_addr, upper_32_bits(res.start)); /*HIGH addr */
154 SDR0_WRITE(sdr_addr + 1, res.start & 0xFFFFFFFF); /* Low addr */ 161 mtdcri(SDR0, *sdr_addr + 1, lower_32_bits(res.start)); /* Low addr */
155
156 162
157 msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi"); 163 msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
158 if (msi->msi_dev) 164 if (!msi->msi_dev)
159 return -ENODEV; 165 return -ENODEV;
160 166
161 msi->msi_regs = of_iomap(msi->msi_dev, 0); 167 msi->msi_regs = of_iomap(msi->msi_dev, 0);
@@ -167,9 +173,12 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
167 (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs)); 173 (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs));
168 174
169 msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL); 175 msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL);
170 msi->msi_addr_hi = 0x0; 176 if (!msi_virt)
171 msi->msi_addr_lo = (u32) msi_phys; 177 return -ENOMEM;
172 dev_dbg(&dev->dev, "PCIE-MSI: msi address 0x%x\n", msi->msi_addr_lo); 178 msi->msi_addr_hi = upper_32_bits(msi_phys);
179 msi->msi_addr_lo = lower_32_bits(msi_phys & 0xffffffff);
180 dev_dbg(&dev->dev, "PCIE-MSI: msi address high 0x%x, low 0x%x\n",
181 msi->msi_addr_hi, msi->msi_addr_lo);
173 182
174 /* Progam the Interrupt handler Termination addr registers */ 183 /* Progam the Interrupt handler Termination addr registers */
175 out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi); 184 out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi);
@@ -185,6 +194,8 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
185 out_be32(msi->msi_regs + PEIH_MSIED, *msi_data); 194 out_be32(msi->msi_regs + PEIH_MSIED, *msi_data);
186 out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask); 195 out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask);
187 196
197 dma_free_coherent(&dev->dev, 64, msi_virt, msi_phys);
198
188 return 0; 199 return 0;
189} 200}
190 201
@@ -194,7 +205,7 @@ static int ppc4xx_of_msi_remove(struct platform_device *dev)
194 int i; 205 int i;
195 int virq; 206 int virq;
196 207
197 for (i = 0; i < NR_MSI_IRQS; i++) { 208 for (i = 0; i < msi_irqs; i++) {
198 virq = msi->msi_virqs[i]; 209 virq = msi->msi_virqs[i];
199 if (virq != NO_IRQ) 210 if (virq != NO_IRQ)
200 irq_dispose_mapping(virq); 211 irq_dispose_mapping(virq);
@@ -215,8 +226,6 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
215 struct resource res; 226 struct resource res;
216 int err = 0; 227 int err = 0;
217 228
218 msi = &ppc4xx_msi;/*keep the msi data for further use*/
219
220 dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n"); 229 dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n");
221 230
222 msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL); 231 msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL);
@@ -234,6 +243,10 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
234 goto error_out; 243 goto error_out;
235 } 244 }
236 245
246 msi_irqs = of_irq_count(dev->dev.of_node);
247 if (!msi_irqs)
248 return -ENODEV;
249
237 if (ppc4xx_setup_pcieh_hw(dev, res, msi)) 250 if (ppc4xx_setup_pcieh_hw(dev, res, msi))
238 goto error_out; 251 goto error_out;
239 252
@@ -242,6 +255,7 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
242 dev_err(&dev->dev, "Error allocating MSI bitmap\n"); 255 dev_err(&dev->dev, "Error allocating MSI bitmap\n");
243 goto error_out; 256 goto error_out;
244 } 257 }
258 ppc4xx_msi = *msi;
245 259
246 ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs; 260 ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs;
247 ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs; 261 ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;