irq-rps.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #include <linux/irqdomain.h>
  2. #include <linux/irq.h>
  3. #include <linux/of.h>
  4. #include <linux/of_address.h>
  5. #include <linux/of_irq.h>
  6. #include <linux/irqchip/chained_irq.h>
  7. #include <linux/err.h>
  8. #include <linux/io.h>
  9. #include <linux/irqchip.h>
  10. struct rps_chip_data {
  11. void __iomem *base;
  12. struct irq_chip chip;
  13. struct irq_domain *domain;
  14. } rps_data;
  15. enum {
  16. RPS_IRQ_BASE = 64,
  17. RPS_IRQ_COUNT = 32,
  18. PRS_HWIRQ_BASE = 0,
  19. RPS_STATUS = 0,
  20. RPS_RAW_STATUS = 4,
  21. RPS_UNMASK = 8,
  22. RPS_MASK = 0xc,
  23. };
  24. /*
  25. * Routines to acknowledge, disable and enable interrupts
  26. */
  27. static void rps_mask_irq(struct irq_data *d)
  28. {
  29. struct rps_chip_data *chip_data = irq_data_get_irq_chip_data(d);
  30. u32 mask = BIT(d->hwirq);
  31. iowrite32(mask, chip_data->base + RPS_MASK);
  32. }
  33. static void rps_unmask_irq(struct irq_data *d)
  34. {
  35. struct rps_chip_data *chip_data = irq_data_get_irq_chip_data(d);
  36. u32 mask = BIT(d->hwirq);
  37. iowrite32(mask, chip_data->base + RPS_UNMASK);
  38. }
  39. static struct irq_chip rps_chip = {
  40. .name = "RPS",
  41. .irq_mask = rps_mask_irq,
  42. .irq_unmask = rps_unmask_irq,
  43. };
  44. static int rps_irq_domain_xlate(struct irq_domain *d,
  45. struct device_node *controller,
  46. const u32 *intspec, unsigned int intsize,
  47. unsigned long *out_hwirq,
  48. unsigned int *out_type)
  49. {
  50. if (irq_domain_get_of_node(d) != controller)
  51. return -EINVAL;
  52. if (intsize < 1)
  53. return -EINVAL;
  54. *out_hwirq = intspec[0];
  55. /* Honestly I do not know the type */
  56. *out_type = IRQ_TYPE_LEVEL_HIGH;
  57. return 0;
  58. }
  59. static int rps_irq_domain_map(struct irq_domain *d, unsigned int irq,
  60. irq_hw_number_t hw)
  61. {
  62. irq_set_chip_and_handler(irq, &rps_chip, handle_level_irq);
  63. irq_set_probe(irq);
  64. irq_set_chip_data(irq, d->host_data);
  65. return 0;
  66. }
  67. const struct irq_domain_ops rps_irq_domain_ops = {
  68. .map = rps_irq_domain_map,
  69. .xlate = rps_irq_domain_xlate,
  70. };
  71. static void rps_handle_cascade_irq(struct irq_desc *desc)
  72. {
  73. struct rps_chip_data *chip_data = irq_desc_get_handler_data(desc);
  74. struct irq_chip *chip = irq_desc_get_chip(desc);
  75. unsigned int cascade_irq, rps_irq;
  76. u32 status;
  77. chained_irq_enter(chip, desc);
  78. status = ioread32(chip_data->base + RPS_STATUS);
  79. rps_irq = __ffs(status);
  80. cascade_irq = irq_find_mapping(chip_data->domain, rps_irq);
  81. if (unlikely(rps_irq >= RPS_IRQ_COUNT))
  82. handle_bad_irq(desc);
  83. else
  84. generic_handle_irq(cascade_irq);
  85. chained_irq_exit(chip, desc);
  86. }
  87. #ifdef CONFIG_OF
  88. int __init rps_of_init(struct device_node *node, struct device_node *parent)
  89. {
  90. void __iomem *rps_base;
  91. int irq_start = RPS_IRQ_BASE;
  92. int irq_base;
  93. int irq;
  94. if (WARN_ON(!node))
  95. return -ENODEV;
  96. rps_base = of_iomap(node, 0);
  97. WARN(!rps_base, "unable to map rps registers\n");
  98. rps_data.base = rps_base;
  99. irq_base = irq_alloc_descs(irq_start, 0, RPS_IRQ_COUNT, numa_node_id());
  100. if (IS_ERR_VALUE(irq_base)) {
  101. WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
  102. irq_start);
  103. irq_base = irq_start;
  104. }
  105. rps_data.domain = irq_domain_add_legacy(node, RPS_IRQ_COUNT, irq_base,
  106. PRS_HWIRQ_BASE, &rps_irq_domain_ops, &rps_data);
  107. if (WARN_ON(!rps_data.domain))
  108. return -ENOMEM;
  109. if (parent) {
  110. irq = irq_of_parse_and_map(node, 0);
  111. if (irq_set_handler_data(irq, &rps_data) != 0)
  112. BUG();
  113. irq_set_chained_handler(irq, rps_handle_cascade_irq);
  114. }
  115. return 0;
  116. }
  117. IRQCHIP_DECLARE(nas782x, "plxtech,nas782x-rps", rps_of_init);
  118. #endif