2
0

0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. From cb376159800b9b44be76949c3aee89eb06d29faa Mon Sep 17 00:00:00 2001
  2. From: John Crispin <[email protected]>
  3. Date: Tue, 6 Mar 2018 09:55:13 +0100
  4. Subject: [PATCH 07/27] irqchip/irq-ath79-intc: add irq cascade driver for
  5. QCA9556 SoCs
  6. Signed-off-by: John Crispin <[email protected]>
  7. ---
  8. drivers/irqchip/Makefile | 1 +
  9. drivers/irqchip/irq-ath79-intc.c | 104 +++++++++++++++++++++++++++++++++++++++
  10. 2 files changed, 105 insertions(+)
  11. create mode 100644 drivers/irqchip/irq-ath79-intc.c
  12. diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
  13. index d27e3e3619e0..f63c94a92e25 100644
  14. --- a/drivers/irqchip/Makefile
  15. +++ b/drivers/irqchip/Makefile
  16. @@ -3,6 +3,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o
  17. obj-$(CONFIG_ALPINE_MSI) += irq-alpine-msi.o
  18. obj-$(CONFIG_ATH79) += irq-ath79-cpu.o
  19. +obj-$(CONFIG_ATH79) += irq-ath79-intc.o
  20. obj-$(CONFIG_ATH79) += irq-ath79-misc.o
  21. obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
  22. obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o
  23. diff --git a/drivers/irqchip/irq-ath79-intc.c b/drivers/irqchip/irq-ath79-intc.c
  24. new file mode 100644
  25. index 000000000000..a26d3efe6e10
  26. --- /dev/null
  27. +++ b/drivers/irqchip/irq-ath79-intc.c
  28. @@ -0,0 +1,104 @@
  29. +/*
  30. + * Atheros AR71xx/AR724x/AR913x specific interrupt handling
  31. + *
  32. + * Copyright (C) 2018 John Crispin <[email protected]>
  33. + *
  34. + * This program is free software; you can redistribute it and/or modify it
  35. + * under the terms of the GNU General Public License version 2 as published
  36. + * by the Free Software Foundation.
  37. + */
  38. +
  39. +#include <linux/interrupt.h>
  40. +#include <linux/irqchip.h>
  41. +#include <linux/of.h>
  42. +#include <linux/of_irq.h>
  43. +#include <linux/irqdomain.h>
  44. +
  45. +#include <asm/irq_cpu.h>
  46. +#include <asm/mach-ath79/ath79.h>
  47. +#include <asm/mach-ath79/ar71xx_regs.h>
  48. +
  49. +#define ATH79_MAX_INTC_CASCADE 3
  50. +
  51. +struct ath79_intc {
  52. + struct irq_chip chip;
  53. + u32 irq;
  54. + u32 pending_mask;
  55. + u32 irq_mask[ATH79_MAX_INTC_CASCADE];
  56. +};
  57. +
  58. +static void ath79_intc_irq_handler(struct irq_desc *desc)
  59. +{
  60. + struct irq_domain *domain = irq_desc_get_handler_data(desc);
  61. + struct ath79_intc *intc = domain->host_data;
  62. + u32 pending;
  63. +
  64. + pending = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
  65. + pending &= intc->pending_mask;
  66. +
  67. + if (pending) {
  68. + int i;
  69. +
  70. + for (i = 0; i < domain->hwirq_max; i++)
  71. + if (pending & intc->irq_mask[i])
  72. + generic_handle_irq(irq_find_mapping(domain, i));
  73. + } else {
  74. + spurious_interrupt();
  75. + }
  76. +}
  77. +
  78. +static void ath79_intc_irq_unmask(struct irq_data *d)
  79. +{
  80. +}
  81. +
  82. +static void ath79_intc_irq_mask(struct irq_data *d)
  83. +{
  84. +}
  85. +
  86. +static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
  87. +{
  88. + struct ath79_intc *intc = d->host_data;
  89. +
  90. + irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq);
  91. +
  92. + return 0;
  93. +}
  94. +
  95. +static const struct irq_domain_ops ath79_irq_domain_ops = {
  96. + .xlate = irq_domain_xlate_onecell,
  97. + .map = ath79_intc_map,
  98. +};
  99. +
  100. +static int __init qca9556_intc_of_init(
  101. + struct device_node *node, struct device_node *parent)
  102. +{
  103. + struct irq_domain *domain;
  104. + struct ath79_intc *intc;
  105. + int cnt, i;
  106. +
  107. + cnt = of_property_count_u32_elems(node, "qcom,pending-bits");
  108. + if (cnt > ATH79_MAX_INTC_CASCADE)
  109. + panic("Too many INTC pending bits\n");
  110. +
  111. + intc = kzalloc(sizeof(*intc), GFP_KERNEL);
  112. + if (!intc)
  113. + panic("Failed to allocate INTC memory\n");
  114. + intc->chip.name = "INTC";
  115. + intc->chip.irq_unmask = ath79_intc_irq_unmask,
  116. + intc->chip.irq_mask = ath79_intc_irq_mask,
  117. +
  118. + of_property_read_u32_array(node, "qcom,pending-bits", intc->irq_mask, cnt);
  119. + for (i = 0; i < cnt; i++)
  120. + intc->pending_mask |= intc->irq_mask[i];
  121. +
  122. + intc->irq = irq_of_parse_and_map(node, 0);
  123. + if (!intc->irq)
  124. + panic("Failed to get INTC IRQ");
  125. +
  126. + domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc);
  127. + irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain);
  128. +
  129. + return 0;
  130. +}
  131. +IRQCHIP_DECLARE(qca9556_intc, "qcom,qca9556-intc",
  132. + qca9556_intc_of_init);
  133. --
  134. 2.11.0