irq-renesas-h8300h.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * H8/300H interrupt controller driver
  3. *
  4. * Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
  5. */
  6. #include <linux/init.h>
  7. #include <linux/irq.h>
  8. #include <linux/irqchip.h>
  9. #include <linux/of_address.h>
  10. #include <linux/of_irq.h>
  11. #include <asm/io.h>
  12. static const char ipr_bit[] = {
  13. 7, 6, 5, 5,
  14. 4, 4, 4, 4, 3, 3, 3, 3,
  15. 2, 2, 2, 2, 1, 1, 1, 1,
  16. 0, 0, 0, 0, 15, 15, 15, 15,
  17. 14, 14, 14, 14, 13, 13, 13, 13,
  18. -1, -1, -1, -1, 11, 11, 11, 11,
  19. 10, 10, 10, 10, 9, 9, 9, 9,
  20. };
  21. static void *intc_baseaddr;
  22. #define IPR ((unsigned long)intc_baseaddr + 6)
  23. static void h8300h_disable_irq(struct irq_data *data)
  24. {
  25. int bit;
  26. int irq = data->irq - 12;
  27. bit = ipr_bit[irq];
  28. if (bit >= 0) {
  29. if (bit < 8)
  30. ctrl_bclr(bit & 7, IPR);
  31. else
  32. ctrl_bclr(bit & 7, (IPR+1));
  33. }
  34. }
  35. static void h8300h_enable_irq(struct irq_data *data)
  36. {
  37. int bit;
  38. int irq = data->irq - 12;
  39. bit = ipr_bit[irq];
  40. if (bit >= 0) {
  41. if (bit < 8)
  42. ctrl_bset(bit & 7, IPR);
  43. else
  44. ctrl_bset(bit & 7, (IPR+1));
  45. }
  46. }
  47. struct irq_chip h8300h_irq_chip = {
  48. .name = "H8/300H-INTC",
  49. .irq_enable = h8300h_enable_irq,
  50. .irq_disable = h8300h_disable_irq,
  51. };
  52. static int irq_map(struct irq_domain *h, unsigned int virq,
  53. irq_hw_number_t hw_irq_num)
  54. {
  55. irq_set_chip_and_handler(virq, &h8300h_irq_chip, handle_simple_irq);
  56. return 0;
  57. }
  58. static struct irq_domain_ops irq_ops = {
  59. .map = irq_map,
  60. .xlate = irq_domain_xlate_onecell,
  61. };
  62. static int __init h8300h_intc_of_init(struct device_node *intc,
  63. struct device_node *parent)
  64. {
  65. struct irq_domain *domain;
  66. intc_baseaddr = of_iomap(intc, 0);
  67. BUG_ON(!intc_baseaddr);
  68. /* All interrupt priority low */
  69. ctrl_outb(0x00, IPR + 0);
  70. ctrl_outb(0x00, IPR + 1);
  71. domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, NULL);
  72. BUG_ON(!domain);
  73. irq_set_default_host(domain);
  74. return 0;
  75. }
  76. IRQCHIP_DECLARE(h8300h_intc, "renesas,h8300h-intc", h8300h_intc_of_init);