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