pq2ads-pci-pic.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * PQ2 ADS-style PCI interrupt controller
  4. *
  5. * Copyright 2007 Freescale Semiconductor, Inc.
  6. * Author: Scott Wood <[email protected]>
  7. *
  8. * Loosely based on mpc82xx ADS support by Vitaly Bordug <[email protected]>
  9. * Copyright (c) 2006 MontaVista Software, Inc.
  10. */
  11. #include <linux/init.h>
  12. #include <linux/spinlock.h>
  13. #include <linux/irq.h>
  14. #include <linux/types.h>
  15. #include <linux/slab.h>
  16. #include <linux/of_irq.h>
  17. #include <asm/io.h>
  18. #include <asm/cpm2.h>
  19. #include "pq2.h"
  20. static DEFINE_RAW_SPINLOCK(pci_pic_lock);
  21. struct pq2ads_pci_pic {
  22. struct device_node *node;
  23. struct irq_domain *host;
  24. struct {
  25. u32 stat;
  26. u32 mask;
  27. } __iomem *regs;
  28. };
  29. #define NUM_IRQS 32
  30. static void pq2ads_pci_mask_irq(struct irq_data *d)
  31. {
  32. struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
  33. int irq = NUM_IRQS - irqd_to_hwirq(d) - 1;
  34. if (irq != -1) {
  35. unsigned long flags;
  36. raw_spin_lock_irqsave(&pci_pic_lock, flags);
  37. setbits32(&priv->regs->mask, 1 << irq);
  38. mb();
  39. raw_spin_unlock_irqrestore(&pci_pic_lock, flags);
  40. }
  41. }
  42. static void pq2ads_pci_unmask_irq(struct irq_data *d)
  43. {
  44. struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
  45. int irq = NUM_IRQS - irqd_to_hwirq(d) - 1;
  46. if (irq != -1) {
  47. unsigned long flags;
  48. raw_spin_lock_irqsave(&pci_pic_lock, flags);
  49. clrbits32(&priv->regs->mask, 1 << irq);
  50. raw_spin_unlock_irqrestore(&pci_pic_lock, flags);
  51. }
  52. }
  53. static struct irq_chip pq2ads_pci_ic = {
  54. .name = "PQ2 ADS PCI",
  55. .irq_mask = pq2ads_pci_mask_irq,
  56. .irq_mask_ack = pq2ads_pci_mask_irq,
  57. .irq_ack = pq2ads_pci_mask_irq,
  58. .irq_unmask = pq2ads_pci_unmask_irq,
  59. .irq_enable = pq2ads_pci_unmask_irq,
  60. .irq_disable = pq2ads_pci_mask_irq
  61. };
  62. static void pq2ads_pci_irq_demux(struct irq_desc *desc)
  63. {
  64. struct pq2ads_pci_pic *priv = irq_desc_get_handler_data(desc);
  65. u32 stat, mask, pend;
  66. int bit;
  67. for (;;) {
  68. stat = in_be32(&priv->regs->stat);
  69. mask = in_be32(&priv->regs->mask);
  70. pend = stat & ~mask;
  71. if (!pend)
  72. break;
  73. for (bit = 0; pend != 0; ++bit, pend <<= 1) {
  74. if (pend & 0x80000000)
  75. generic_handle_domain_irq(priv->host, bit);
  76. }
  77. }
  78. }
  79. static int pci_pic_host_map(struct irq_domain *h, unsigned int virq,
  80. irq_hw_number_t hw)
  81. {
  82. irq_set_status_flags(virq, IRQ_LEVEL);
  83. irq_set_chip_data(virq, h->host_data);
  84. irq_set_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq);
  85. return 0;
  86. }
  87. static const struct irq_domain_ops pci_pic_host_ops = {
  88. .map = pci_pic_host_map,
  89. };
  90. int __init pq2ads_pci_init_irq(void)
  91. {
  92. struct pq2ads_pci_pic *priv;
  93. struct irq_domain *host;
  94. struct device_node *np;
  95. int ret = -ENODEV;
  96. int irq;
  97. np = of_find_compatible_node(NULL, NULL, "fsl,pq2ads-pci-pic");
  98. if (!np) {
  99. printk(KERN_ERR "No pci pic node in device tree.\n");
  100. goto out;
  101. }
  102. irq = irq_of_parse_and_map(np, 0);
  103. if (!irq) {
  104. printk(KERN_ERR "No interrupt in pci pic node.\n");
  105. goto out_put_node;
  106. }
  107. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  108. if (!priv) {
  109. ret = -ENOMEM;
  110. goto out_unmap_irq;
  111. }
  112. /* PCI interrupt controller registers: status and mask */
  113. priv->regs = of_iomap(np, 0);
  114. if (!priv->regs) {
  115. printk(KERN_ERR "Cannot map PCI PIC registers.\n");
  116. goto out_free_kmalloc;
  117. }
  118. /* mask all PCI interrupts */
  119. out_be32(&priv->regs->mask, ~0);
  120. mb();
  121. host = irq_domain_add_linear(np, NUM_IRQS, &pci_pic_host_ops, priv);
  122. if (!host) {
  123. ret = -ENOMEM;
  124. goto out_unmap_regs;
  125. }
  126. priv->host = host;
  127. irq_set_handler_data(irq, priv);
  128. irq_set_chained_handler(irq, pq2ads_pci_irq_demux);
  129. ret = 0;
  130. goto out_put_node;
  131. out_unmap_regs:
  132. iounmap(priv->regs);
  133. out_free_kmalloc:
  134. kfree(priv);
  135. out_unmap_irq:
  136. irq_dispose_mapping(irq);
  137. out_put_node:
  138. of_node_put(np);
  139. out:
  140. return ret;
  141. }