irq-bcm7120-l2.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Broadcom BCM7120 style Level 2 interrupt controller driver
  3. *
  4. * Copyright (C) 2014 Broadcom Corporation
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11. #include <linux/init.h>
  12. #include <linux/slab.h>
  13. #include <linux/module.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/of.h>
  16. #include <linux/of_irq.h>
  17. #include <linux/of_address.h>
  18. #include <linux/of_platform.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/irq.h>
  21. #include <linux/io.h>
  22. #include <linux/irqdomain.h>
  23. #include <linux/reboot.h>
  24. #include <linux/irqchip/chained_irq.h>
  25. #include "irqchip.h"
  26. #include <asm/mach/irq.h>
  27. /* Register offset in the L2 interrupt controller */
  28. #define IRQEN 0x00
  29. #define IRQSTAT 0x04
  30. struct bcm7120_l2_intc_data {
  31. void __iomem *base;
  32. struct irq_domain *domain;
  33. bool can_wake;
  34. u32 irq_fwd_mask;
  35. u32 irq_map_mask;
  36. u32 saved_mask;
  37. };
  38. static void bcm7120_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
  39. {
  40. struct bcm7120_l2_intc_data *b = irq_desc_get_handler_data(desc);
  41. struct irq_chip *chip = irq_desc_get_chip(desc);
  42. u32 status;
  43. chained_irq_enter(chip, desc);
  44. status = __raw_readl(b->base + IRQSTAT);
  45. if (status == 0) {
  46. do_bad_IRQ(irq, desc);
  47. goto out;
  48. }
  49. do {
  50. irq = ffs(status) - 1;
  51. status &= ~(1 << irq);
  52. generic_handle_irq(irq_find_mapping(b->domain, irq));
  53. } while (status);
  54. out:
  55. chained_irq_exit(chip, desc);
  56. }
  57. static void bcm7120_l2_intc_suspend(struct irq_data *d)
  58. {
  59. struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
  60. struct bcm7120_l2_intc_data *b = gc->private;
  61. u32 reg;
  62. irq_gc_lock(gc);
  63. /* Save the current mask and the interrupt forward mask */
  64. b->saved_mask = __raw_readl(b->base) | b->irq_fwd_mask;
  65. if (b->can_wake) {
  66. reg = b->saved_mask | gc->wake_active;
  67. __raw_writel(reg, b->base);
  68. }
  69. irq_gc_unlock(gc);
  70. }
  71. static void bcm7120_l2_intc_resume(struct irq_data *d)
  72. {
  73. struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
  74. struct bcm7120_l2_intc_data *b = gc->private;
  75. /* Restore the saved mask */
  76. irq_gc_lock(gc);
  77. __raw_writel(b->saved_mask, b->base);
  78. irq_gc_unlock(gc);
  79. }
  80. static int bcm7120_l2_intc_init_one(struct device_node *dn,
  81. struct bcm7120_l2_intc_data *data,
  82. int irq, const __be32 *map_mask)
  83. {
  84. int parent_irq;
  85. parent_irq = irq_of_parse_and_map(dn, irq);
  86. if (parent_irq < 0) {
  87. pr_err("failed to map interrupt %d\n", irq);
  88. return parent_irq;
  89. }
  90. data->irq_map_mask |= be32_to_cpup(map_mask + irq);
  91. irq_set_handler_data(parent_irq, data);
  92. irq_set_chained_handler(parent_irq, bcm7120_l2_intc_irq_handle);
  93. return 0;
  94. }
  95. int __init bcm7120_l2_intc_of_init(struct device_node *dn,
  96. struct device_node *parent)
  97. {
  98. unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
  99. struct bcm7120_l2_intc_data *data;
  100. struct irq_chip_generic *gc;
  101. struct irq_chip_type *ct;
  102. const __be32 *map_mask;
  103. int num_parent_irqs;
  104. int ret = 0, len, irq;
  105. data = kzalloc(sizeof(*data), GFP_KERNEL);
  106. if (!data)
  107. return -ENOMEM;
  108. data->base = of_iomap(dn, 0);
  109. if (!data->base) {
  110. pr_err("failed to remap intc L2 registers\n");
  111. ret = -ENOMEM;
  112. goto out_free;
  113. }
  114. if (of_property_read_u32(dn, "brcm,int-fwd-mask", &data->irq_fwd_mask))
  115. data->irq_fwd_mask = 0;
  116. /* Enable all interrupt specified in the interrupt forward mask and have
  117. * the other disabled
  118. */
  119. __raw_writel(data->irq_fwd_mask, data->base + IRQEN);
  120. num_parent_irqs = of_irq_count(dn);
  121. if (num_parent_irqs <= 0) {
  122. pr_err("invalid number of parent interrupts\n");
  123. ret = -ENOMEM;
  124. goto out_unmap;
  125. }
  126. map_mask = of_get_property(dn, "brcm,int-map-mask", &len);
  127. if (!map_mask || (len != (sizeof(*map_mask) * num_parent_irqs))) {
  128. pr_err("invalid brcm,int-map-mask property\n");
  129. ret = -EINVAL;
  130. goto out_unmap;
  131. }
  132. for (irq = 0; irq < num_parent_irqs; irq++) {
  133. ret = bcm7120_l2_intc_init_one(dn, data, irq, map_mask);
  134. if (ret)
  135. goto out_unmap;
  136. }
  137. data->domain = irq_domain_add_linear(dn, 32,
  138. &irq_generic_chip_ops, NULL);
  139. if (!data->domain) {
  140. ret = -ENOMEM;
  141. goto out_unmap;
  142. }
  143. ret = irq_alloc_domain_generic_chips(data->domain, 32, 1,
  144. dn->full_name, handle_level_irq, clr, 0,
  145. IRQ_GC_INIT_MASK_CACHE);
  146. if (ret) {
  147. pr_err("failed to allocate generic irq chip\n");
  148. goto out_free_domain;
  149. }
  150. gc = irq_get_domain_generic_chip(data->domain, 0);
  151. gc->unused = 0xfffffff & ~data->irq_map_mask;
  152. gc->reg_base = data->base;
  153. gc->private = data;
  154. ct = gc->chip_types;
  155. ct->regs.mask = IRQEN;
  156. ct->chip.irq_mask = irq_gc_mask_clr_bit;
  157. ct->chip.irq_unmask = irq_gc_mask_set_bit;
  158. ct->chip.irq_ack = irq_gc_noop;
  159. ct->chip.irq_suspend = bcm7120_l2_intc_suspend;
  160. ct->chip.irq_resume = bcm7120_l2_intc_resume;
  161. if (of_property_read_bool(dn, "brcm,irq-can-wake")) {
  162. data->can_wake = true;
  163. /* This IRQ chip can wake the system, set all relevant child
  164. * interupts in wake_enabled mask
  165. */
  166. gc->wake_enabled = 0xffffffff;
  167. gc->wake_enabled &= ~gc->unused;
  168. ct->chip.irq_set_wake = irq_gc_set_wake;
  169. }
  170. pr_info("registered BCM7120 L2 intc (mem: 0x%p, parent IRQ(s): %d)\n",
  171. data->base, num_parent_irqs);
  172. return 0;
  173. out_free_domain:
  174. irq_domain_remove(data->domain);
  175. out_unmap:
  176. iounmap(data->base);
  177. out_free:
  178. kfree(data);
  179. return ret;
  180. }
  181. IRQCHIP_DECLARE(brcmstb_l2_intc, "brcm,bcm7120-l2-intc",
  182. bcm7120_l2_intc_of_init);