irq-ativic32.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2005-2017 Andes Technology Corporation
  3. #include <linux/irq.h>
  4. #include <linux/of.h>
  5. #include <linux/of_irq.h>
  6. #include <linux/of_address.h>
  7. #include <linux/interrupt.h>
  8. #include <linux/irqdomain.h>
  9. #include <linux/irqchip.h>
  10. #include <nds32_intrinsic.h>
  11. unsigned long wake_mask;
  12. static void ativic32_ack_irq(struct irq_data *data)
  13. {
  14. __nds32__mtsr_dsb(BIT(data->hwirq), NDS32_SR_INT_PEND2);
  15. }
  16. static void ativic32_mask_irq(struct irq_data *data)
  17. {
  18. unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
  19. __nds32__mtsr_dsb(int_mask2 & (~(BIT(data->hwirq))), NDS32_SR_INT_MASK2);
  20. }
  21. static void ativic32_unmask_irq(struct irq_data *data)
  22. {
  23. unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
  24. __nds32__mtsr_dsb(int_mask2 | (BIT(data->hwirq)), NDS32_SR_INT_MASK2);
  25. }
  26. static int nointc_set_wake(struct irq_data *data, unsigned int on)
  27. {
  28. unsigned long int_mask = __nds32__mfsr(NDS32_SR_INT_MASK);
  29. static unsigned long irq_orig_bit;
  30. u32 bit = 1 << data->hwirq;
  31. if (on) {
  32. if (int_mask & bit)
  33. __assign_bit(data->hwirq, &irq_orig_bit, true);
  34. else
  35. __assign_bit(data->hwirq, &irq_orig_bit, false);
  36. __assign_bit(data->hwirq, &int_mask, true);
  37. __assign_bit(data->hwirq, &wake_mask, true);
  38. } else {
  39. if (!(irq_orig_bit & bit))
  40. __assign_bit(data->hwirq, &int_mask, false);
  41. __assign_bit(data->hwirq, &wake_mask, false);
  42. __assign_bit(data->hwirq, &irq_orig_bit, false);
  43. }
  44. __nds32__mtsr_dsb(int_mask, NDS32_SR_INT_MASK);
  45. return 0;
  46. }
  47. static struct irq_chip ativic32_chip = {
  48. .name = "ativic32",
  49. .irq_ack = ativic32_ack_irq,
  50. .irq_mask = ativic32_mask_irq,
  51. .irq_unmask = ativic32_unmask_irq,
  52. .irq_set_wake = nointc_set_wake,
  53. };
  54. static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 };
  55. static struct irq_domain *root_domain;
  56. static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq,
  57. irq_hw_number_t hw)
  58. {
  59. unsigned long int_trigger_type;
  60. u32 type;
  61. struct irq_data *irq_data;
  62. int_trigger_type = __nds32__mfsr(NDS32_SR_INT_TRIGGER);
  63. irq_data = irq_get_irq_data(virq);
  64. if (!irq_data)
  65. return -EINVAL;
  66. if (int_trigger_type & (BIT(hw))) {
  67. irq_set_chip_and_handler(virq, &ativic32_chip, handle_edge_irq);
  68. type = IRQ_TYPE_EDGE_RISING;
  69. } else {
  70. irq_set_chip_and_handler(virq, &ativic32_chip, handle_level_irq);
  71. type = IRQ_TYPE_LEVEL_HIGH;
  72. }
  73. irqd_set_trigger_type(irq_data, type);
  74. return 0;
  75. }
  76. static const struct irq_domain_ops ativic32_ops = {
  77. .map = ativic32_irq_domain_map,
  78. .xlate = irq_domain_xlate_onecell
  79. };
  80. static irq_hw_number_t get_intr_src(void)
  81. {
  82. return ((__nds32__mfsr(NDS32_SR_ITYPE) & ITYPE_mskVECTOR) >> ITYPE_offVECTOR)
  83. - NDS32_VECTOR_offINTERRUPT;
  84. }
  85. asmlinkage void asm_do_IRQ(struct pt_regs *regs)
  86. {
  87. irq_hw_number_t hwirq = get_intr_src();
  88. handle_domain_irq(root_domain, hwirq, regs);
  89. }
  90. int __init ativic32_init_irq(struct device_node *node, struct device_node *parent)
  91. {
  92. unsigned long int_vec_base, nivic, nr_ints;
  93. if (WARN(parent, "non-root ativic32 are not supported"))
  94. return -EINVAL;
  95. int_vec_base = __nds32__mfsr(NDS32_SR_IVB);
  96. if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0)
  97. panic("Unable to use atcivic32 for this cpu.\n");
  98. nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC;
  99. if (nivic >= ARRAY_SIZE(nivic_map))
  100. panic("The number of input for ativic32 is not supported.\n");
  101. nr_ints = nivic_map[nivic];
  102. root_domain = irq_domain_add_linear(node, nr_ints,
  103. &ativic32_ops, NULL);
  104. if (!root_domain)
  105. panic("%s: unable to create IRQ domain\n", node->full_name);
  106. return 0;
  107. }
  108. IRQCHIP_DECLARE(ativic32, "andestech,ativic32", ativic32_init_irq);