Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/44x: Fix PCI MSI support for Maui APM821xx SoC and Bluestone board

This patch consists of:
- Enable PCI MSI as default for Bluestone board
- Change definition of number of MSI interrupts as it depends on SoC
- Fix returning ENODEV as finding MSI node
- Fix MSI physical high and low address
- Keep MSI data logically

Signed-off-by: Mai La <mla@apm.com>
Signed-off-by: Josh Boyer <jwboyer@gmail.com>

authored by

Mai La and committed by
Josh Boyer
247540b0 47da4219

+30 -14
+2
arch/powerpc/platforms/44x/Kconfig
··· 23 23 default n 24 24 select PPC44x_SIMPLE 25 25 select APM821xx 26 + select PCI_MSI 27 + select PPC4xx_MSI 26 28 select PPC4xx_PCI_EXPRESS 27 29 select IBM_EMAC_RGMII 28 30 help
+28 -14
arch/powerpc/sysdev/ppc4xx_msi.c
··· 28 28 #include <linux/of_platform.h> 29 29 #include <linux/interrupt.h> 30 30 #include <linux/export.h> 31 + #include <linux/kernel.h> 31 32 #include <asm/prom.h> 32 33 #include <asm/hw_irq.h> 33 34 #include <asm/ppc-pci.h> 34 - #include <boot/dcr.h> 35 + #include <asm/dcr.h> 35 36 #include <asm/dcr-regs.h> 36 37 #include <asm/msi_bitmap.h> 37 38 ··· 44 43 #define PEIH_FLUSH0 0x30 45 44 #define PEIH_FLUSH1 0x38 46 45 #define PEIH_CNTRST 0x48 47 - #define NR_MSI_IRQS 4 46 + 47 + static int msi_irqs; 48 48 49 49 struct ppc4xx_msi { 50 50 u32 msi_addr_lo; 51 51 u32 msi_addr_hi; 52 52 void __iomem *msi_regs; 53 - int msi_virqs[NR_MSI_IRQS]; 53 + int *msi_virqs; 54 54 struct msi_bitmap bitmap; 55 55 struct device_node *msi_dev; 56 56 }; ··· 63 61 { 64 62 int err; 65 63 66 - err = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, 64 + err = msi_bitmap_alloc(&msi_data->bitmap, msi_irqs, 67 65 dev->dev.of_node); 68 66 if (err) 69 67 return err; ··· 84 82 struct msi_msg msg; 85 83 struct msi_desc *entry; 86 84 struct ppc4xx_msi *msi_data = &ppc4xx_msi; 85 + 86 + msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int), 87 + GFP_KERNEL); 88 + if (!msi_data->msi_virqs) 89 + return -ENOMEM; 87 90 88 91 list_for_each_entry(entry, &dev->msi_list, list) { 89 92 int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); ··· 157 150 if (!sdr_addr) 158 151 return -1; 159 152 160 - SDR0_WRITE(sdr_addr, (u64)res.start >> 32); /*HIGH addr */ 161 - SDR0_WRITE(sdr_addr + 1, res.start & 0xFFFFFFFF); /* Low addr */ 162 - 153 + mtdcri(SDR0, *sdr_addr, upper_32_bits(res.start)); /*HIGH addr */ 154 + mtdcri(SDR0, *sdr_addr + 1, lower_32_bits(res.start)); /* Low addr */ 163 155 164 156 msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi"); 165 - if (msi->msi_dev) 157 + if (!msi->msi_dev) 166 158 return -ENODEV; 167 159 168 160 msi->msi_regs = of_iomap(msi->msi_dev, 0); ··· 173 167 (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs)); 174 168 175 169 msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL); 176 - msi->msi_addr_hi = 0x0; 177 - msi->msi_addr_lo = (u32) msi_phys; 178 - dev_dbg(&dev->dev, "PCIE-MSI: msi address 0x%x\n", msi->msi_addr_lo); 170 + if (!msi_virt) 171 + return -ENOMEM; 172 + msi->msi_addr_hi = (u32)(msi_phys >> 32); 173 + msi->msi_addr_lo = (u32)(msi_phys & 0xffffffff); 174 + dev_dbg(&dev->dev, "PCIE-MSI: msi address high 0x%x, low 0x%x\n", 175 + msi->msi_addr_hi, msi->msi_addr_lo); 179 176 180 177 /* Progam the Interrupt handler Termination addr registers */ 181 178 out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi); ··· 194 185 out_be32(msi->msi_regs + PEIH_MSIED, *msi_data); 195 186 out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask); 196 187 188 + dma_free_coherent(&dev->dev, 64, msi_virt, msi_phys); 189 + 197 190 return 0; 198 191 } 199 192 ··· 205 194 int i; 206 195 int virq; 207 196 208 - for (i = 0; i < NR_MSI_IRQS; i++) { 197 + for (i = 0; i < msi_irqs; i++) { 209 198 virq = msi->msi_virqs[i]; 210 199 if (virq != NO_IRQ) 211 200 irq_dispose_mapping(virq); ··· 226 215 struct resource res; 227 216 int err = 0; 228 217 229 - msi = &ppc4xx_msi;/*keep the msi data for further use*/ 230 - 231 218 dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n"); 232 219 233 220 msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL); ··· 243 234 goto error_out; 244 235 } 245 236 237 + msi_irqs = of_irq_count(dev->dev.of_node); 238 + if (!msi_irqs) 239 + return -ENODEV; 240 + 246 241 if (ppc4xx_setup_pcieh_hw(dev, res, msi)) 247 242 goto error_out; 248 243 ··· 255 242 dev_err(&dev->dev, "Error allocating MSI bitmap\n"); 256 243 goto error_out; 257 244 } 245 + ppc4xx_msi = *msi; 258 246 259 247 ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs; 260 248 ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;