irqdomain.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /*
  2. * IRQ domain support for SH INTC subsystem
  3. *
  4. * Copyright (C) 2012 Paul Mundt
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file "COPYING" in the main directory of this archive
  8. * for more details.
  9. */
  10. #define pr_fmt(fmt) "intc: " fmt
  11. #include <linux/irqdomain.h>
  12. #include <linux/sh_intc.h>
  13. #include <linux/export.h>
  14. #include "internals.h"
  15. /**
  16. * intc_irq_domain_evt_xlate() - Generic xlate for vectored IRQs.
  17. *
  18. * This takes care of exception vector to hwirq translation through
  19. * by way of evt2irq() translation.
  20. *
  21. * Note: For platforms that use a flat vector space without INTEVT this
  22. * basically just mimics irq_domain_xlate_onecell() by way of a nopped
  23. * out evt2irq() implementation.
  24. */
  25. static int intc_evt_xlate(struct irq_domain *d, struct device_node *ctrlr,
  26. const u32 *intspec, unsigned int intsize,
  27. unsigned long *out_hwirq, unsigned int *out_type)
  28. {
  29. if (WARN_ON(intsize < 1))
  30. return -EINVAL;
  31. *out_hwirq = evt2irq(intspec[0]);
  32. *out_type = IRQ_TYPE_NONE;
  33. return 0;
  34. }
  35. static const struct irq_domain_ops intc_evt_ops = {
  36. .xlate = intc_evt_xlate,
  37. };
  38. void __init intc_irq_domain_init(struct intc_desc_int *d,
  39. struct intc_hw_desc *hw)
  40. {
  41. unsigned int irq_base, irq_end;
  42. /*
  43. * Quick linear revmap check
  44. */
  45. irq_base = evt2irq(hw->vectors[0].vect);
  46. irq_end = evt2irq(hw->vectors[hw->nr_vectors - 1].vect);
  47. /*
  48. * Linear domains have a hard-wired assertion that IRQs start at
  49. * 0 in order to make some performance optimizations. Lamely
  50. * restrict the linear case to these conditions here, taking the
  51. * tree penalty for linear cases with non-zero hwirq bases.
  52. */
  53. if (irq_base == 0 && irq_end == (irq_base + hw->nr_vectors - 1))
  54. d->domain = irq_domain_add_linear(NULL, hw->nr_vectors,
  55. &intc_evt_ops, NULL);
  56. else
  57. d->domain = irq_domain_add_tree(NULL, &intc_evt_ops, NULL);
  58. BUG_ON(!d->domain);
  59. }