1 /* 2 * Copyright (C) 2007-2010 Freescale Semiconductor, Inc. 3 * 4 * Author: Tony Li <tony.li@freescale.com> 5 * Jason Jin <Jason.jin@freescale.com> 6 * 7 * The hwirq alloc and free code reuse from sysdev/mpic_msi.c 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * as published by the Free Software Foundation; version 2 of the 12 * License. 13 * 14 */ 15 #include <linux/irq.h> 16 #include <linux/bootmem.h> 17 #include <linux/msi.h> 18 #include <linux/pci.h> 19 #include <linux/slab.h> 20 #include <linux/of_platform.h> 21 #include <sysdev/fsl_soc.h> 22 #include <asm/prom.h> 23 #include <asm/hw_irq.h> 24 #include <asm/ppc-pci.h> 25 #include <asm/mpic.h> 26 #include "fsl_msi.h" 27 #include "fsl_pci.h" 28 29 LIST_HEAD(msi_head); 30 31 struct fsl_msi_feature { 32 u32 fsl_pic_ip; 33 u32 msiir_offset; 34 }; 35 36 struct fsl_msi_cascade_data { 37 struct fsl_msi *msi_data; 38 int index; 39 }; 40 41 static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) 42 { 43 return in_be32(base + (reg >> 2)); 44 } 45 46 /* 47 * We do not need this actually. The MSIR register has been read once 48 * in the cascade interrupt. So, this MSI interrupt has been acked 49 */ 50 static void fsl_msi_end_irq(unsigned int virq) 51 { 52 } 53 54 static struct irq_chip fsl_msi_chip = { 55 .irq_mask = mask_msi_irq, 56 .irq_unmask = unmask_msi_irq, 57 .ack = fsl_msi_end_irq, 58 .name = "FSL-MSI", 59 }; 60 61 static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, 62 irq_hw_number_t hw) 63 { 64 struct fsl_msi *msi_data = h->host_data; 65 struct irq_chip *chip = &fsl_msi_chip; 66 67 irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; 68 69 set_irq_chip_data(virq, msi_data); 70 set_irq_chip_and_handler(virq, chip, handle_edge_irq); 71 72 return 0; 73 } 74 75 static struct irq_host_ops fsl_msi_host_ops = { 76 .map = fsl_msi_host_map, 77 }; 78 79 static int fsl_msi_init_allocator(struct fsl_msi *msi_data) 80 { 81 int rc; 82 83 rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, 84 msi_data->irqhost->of_node); 85 if (rc) 86 return rc; 87 88 rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap); 89 if (rc < 0) { 90 msi_bitmap_free(&msi_data->bitmap); 91 return rc; 92 } 93 94 return 0; 95 } 96 97 static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) 98 { 99 if (type == PCI_CAP_ID_MSIX) 100 pr_debug("fslmsi: MSI-X untested, trying anyway.\n"); 101 102 return 0; 103 } 104 105 static void fsl_teardown_msi_irqs(struct pci_dev *pdev) 106 { 107 struct msi_desc *entry; 108 struct fsl_msi *msi_data; 109 110 list_for_each_entry(entry, &pdev->msi_list, list) { 111 if (entry->irq == NO_IRQ) 112 continue; 113 msi_data = get_irq_data(entry->irq); 114 set_irq_msi(entry->irq, NULL); 115 msi_bitmap_free_hwirqs(&msi_data->bitmap, 116 virq_to_hw(entry->irq), 1); 117 irq_dispose_mapping(entry->irq); 118 } 119 120 return; 121 } 122 123 static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, 124 struct msi_msg *msg, 125 struct fsl_msi *fsl_msi_data) 126 { 127 struct fsl_msi *msi_data = fsl_msi_data; 128 struct pci_controller *hose = pci_bus_to_host(pdev->bus); 129 u64 base = fsl_pci_immrbar_base(hose); 130 131 msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base); 132 msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base); 133 134 msg->data = hwirq; 135 136 pr_debug("%s: allocated srs: %d, ibs: %d\n", 137 __func__, hwirq / IRQS_PER_MSI_REG, hwirq % IRQS_PER_MSI_REG); 138 } 139 140 static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 141 { 142 int rc, hwirq = -ENOMEM; 143 unsigned int virq; 144 struct msi_desc *entry; 145 struct msi_msg msg; 146 struct fsl_msi *msi_data; 147 148 list_for_each_entry(entry, &pdev->msi_list, list) { 149 list_for_each_entry(msi_data, &msi_head, list) { 150 hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); 151 if (hwirq >= 0) 152 break; 153 } 154 155 if (hwirq < 0) { 156 rc = hwirq; 157 pr_debug("%s: fail allocating msi interrupt\n", 158 __func__); 159 goto out_free; 160 } 161 162 virq = irq_create_mapping(msi_data->irqhost, hwirq); 163 164 if (virq == NO_IRQ) { 165 pr_debug("%s: fail mapping hwirq 0x%x\n", 166 __func__, hwirq); 167 msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1); 168 rc = -ENOSPC; 169 goto out_free; 170 } 171 set_irq_data(virq, msi_data); 172 set_irq_msi(virq, entry); 173 174 fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data); 175 write_msi_msg(virq, &msg); 176 } 177 return 0; 178 179 out_free: 180 /* free by the caller of this function */ 181 return rc; 182 } 183 184 static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) 185 { 186 unsigned int cascade_irq; 187 struct fsl_msi *msi_data; 188 int msir_index = -1; 189 u32 msir_value = 0; 190 u32 intr_index; 191 u32 have_shift = 0; 192 struct fsl_msi_cascade_data *cascade_data; 193 194 cascade_data = (struct fsl_msi_cascade_data *)get_irq_data(irq); 195 msi_data = cascade_data->msi_data; 196 197 raw_spin_lock(&desc->lock); 198 if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { 199 if (desc->chip->mask_ack) 200 desc->chip->mask_ack(irq); 201 else { 202 desc->chip->mask(irq); 203 desc->chip->ack(irq); 204 } 205 } 206 207 if (unlikely(desc->status & IRQ_INPROGRESS)) 208 goto unlock; 209 210 msir_index = cascade_data->index; 211 212 if (msir_index >= NR_MSI_REG) 213 cascade_irq = NO_IRQ; 214 215 desc->status |= IRQ_INPROGRESS; 216 switch (msi_data->feature & FSL_PIC_IP_MASK) { 217 case FSL_PIC_IP_MPIC: 218 msir_value = fsl_msi_read(msi_data->msi_regs, 219 msir_index * 0x10); 220 break; 221 case FSL_PIC_IP_IPIC: 222 msir_value = fsl_msi_read(msi_data->msi_regs, msir_index * 0x4); 223 break; 224 } 225 226 while (msir_value) { 227 intr_index = ffs(msir_value) - 1; 228 229 cascade_irq = irq_linear_revmap(msi_data->irqhost, 230 msir_index * IRQS_PER_MSI_REG + 231 intr_index + have_shift); 232 if (cascade_irq != NO_IRQ) 233 generic_handle_irq(cascade_irq); 234 have_shift += intr_index + 1; 235 msir_value = msir_value >> (intr_index + 1); 236 } 237 desc->status &= ~IRQ_INPROGRESS; 238 239 switch (msi_data->feature & FSL_PIC_IP_MASK) { 240 case FSL_PIC_IP_MPIC: 241 desc->chip->eoi(irq); 242 break; 243 case FSL_PIC_IP_IPIC: 244 if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) 245 desc->chip->unmask(irq); 246 break; 247 } 248 unlock: 249 raw_spin_unlock(&desc->lock); 250 } 251 252 static int fsl_of_msi_remove(struct platform_device *ofdev) 253 { 254 struct fsl_msi *msi = ofdev->dev.platform_data; 255 int virq, i; 256 struct fsl_msi_cascade_data *cascade_data; 257 258 if (msi->list.prev != NULL) 259 list_del(&msi->list); 260 for (i = 0; i < NR_MSI_REG; i++) { 261 virq = msi->msi_virqs[i]; 262 if (virq != NO_IRQ) { 263 cascade_data = get_irq_data(virq); 264 kfree(cascade_data); 265 irq_dispose_mapping(virq); 266 } 267 } 268 if (msi->bitmap.bitmap) 269 msi_bitmap_free(&msi->bitmap); 270 iounmap(msi->msi_regs); 271 kfree(msi); 272 273 return 0; 274 } 275 276 static int __devinit fsl_of_msi_probe(struct platform_device *dev, 277 const struct of_device_id *match) 278 { 279 struct fsl_msi *msi; 280 struct resource res; 281 int err, i, count; 282 int rc; 283 int virt_msir; 284 const u32 *p; 285 struct fsl_msi_feature *features = match->data; 286 struct fsl_msi_cascade_data *cascade_data = NULL; 287 int len; 288 u32 offset; 289 290 printk(KERN_DEBUG "Setting up Freescale MSI support\n"); 291 292 msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); 293 if (!msi) { 294 dev_err(&dev->dev, "No memory for MSI structure\n"); 295 return -ENOMEM; 296 } 297 dev->dev.platform_data = msi; 298 299 msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR, 300 NR_MSI_IRQS, &fsl_msi_host_ops, 0); 301 302 if (msi->irqhost == NULL) { 303 dev_err(&dev->dev, "No memory for MSI irqhost\n"); 304 err = -ENOMEM; 305 goto error_out; 306 } 307 308 /* Get the MSI reg base */ 309 err = of_address_to_resource(dev->dev.of_node, 0, &res); 310 if (err) { 311 dev_err(&dev->dev, "%s resource error!\n", 312 dev->dev.of_node->full_name); 313 goto error_out; 314 } 315 316 msi->msi_regs = ioremap(res.start, res.end - res.start + 1); 317 if (!msi->msi_regs) { 318 dev_err(&dev->dev, "ioremap problem failed\n"); 319 goto error_out; 320 } 321 322 msi->feature = features->fsl_pic_ip; 323 324 msi->irqhost->host_data = msi; 325 326 msi->msi_addr_hi = 0x0; 327 msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff); 328 329 rc = fsl_msi_init_allocator(msi); 330 if (rc) { 331 dev_err(&dev->dev, "Error allocating MSI bitmap\n"); 332 goto error_out; 333 } 334 335 p = of_get_property(dev->dev.of_node, "interrupts", &count); 336 if (!p) { 337 dev_err(&dev->dev, "no interrupts property found on %s\n", 338 dev->dev.of_node->full_name); 339 err = -ENODEV; 340 goto error_out; 341 } 342 if (count % 8 != 0) { 343 dev_err(&dev->dev, "Malformed interrupts property on %s\n", 344 dev->dev.of_node->full_name); 345 err = -EINVAL; 346 goto error_out; 347 } 348 offset = 0; 349 p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len); 350 if (p) 351 offset = *p / IRQS_PER_MSI_REG; 352 353 count /= sizeof(u32); 354 for (i = 0; i < min(count / 2, NR_MSI_REG); i++) { 355 virt_msir = irq_of_parse_and_map(dev->dev.of_node, i); 356 if (virt_msir != NO_IRQ) { 357 cascade_data = kzalloc( 358 sizeof(struct fsl_msi_cascade_data), 359 GFP_KERNEL); 360 if (!cascade_data) { 361 dev_err(&dev->dev, 362 "No memory for MSI cascade data\n"); 363 err = -ENOMEM; 364 goto error_out; 365 } 366 msi->msi_virqs[i] = virt_msir; 367 cascade_data->index = i + offset; 368 cascade_data->msi_data = msi; 369 set_irq_data(virt_msir, (void *)cascade_data); 370 set_irq_chained_handler(virt_msir, fsl_msi_cascade); 371 } 372 } 373 374 list_add_tail(&msi->list, &msi_head); 375 376 /* The multiple setting ppc_md.setup_msi_irqs will not harm things */ 377 if (!ppc_md.setup_msi_irqs) { 378 ppc_md.setup_msi_irqs = fsl_setup_msi_irqs; 379 ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs; 380 ppc_md.msi_check_device = fsl_msi_check_device; 381 } else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) { 382 dev_err(&dev->dev, "Different MSI driver already installed!\n"); 383 err = -ENODEV; 384 goto error_out; 385 } 386 return 0; 387 error_out: 388 fsl_of_msi_remove(dev); 389 return err; 390 } 391 392 static const struct fsl_msi_feature mpic_msi_feature = { 393 .fsl_pic_ip = FSL_PIC_IP_MPIC, 394 .msiir_offset = 0x140, 395 }; 396 397 static const struct fsl_msi_feature ipic_msi_feature = { 398 .fsl_pic_ip = FSL_PIC_IP_IPIC, 399 .msiir_offset = 0x38, 400 }; 401 402 static const struct of_device_id fsl_of_msi_ids[] = { 403 { 404 .compatible = "fsl,mpic-msi", 405 .data = (void *)&mpic_msi_feature, 406 }, 407 { 408 .compatible = "fsl,ipic-msi", 409 .data = (void *)&ipic_msi_feature, 410 }, 411 {} 412 }; 413 414 static struct of_platform_driver fsl_of_msi_driver = { 415 .driver = { 416 .name = "fsl-msi", 417 .owner = THIS_MODULE, 418 .of_match_table = fsl_of_msi_ids, 419 }, 420 .probe = fsl_of_msi_probe, 421 .remove = fsl_of_msi_remove, 422 }; 423 424 static __init int fsl_of_msi_init(void) 425 { 426 return of_register_platform_driver(&fsl_of_msi_driver); 427 } 428 429 subsys_initcall(fsl_of_msi_init); 430