irq-mb93493.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /* irq-mb93493.c: MB93493 companion chip interrupt handler
  2. *
  3. * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/ptrace.h>
  12. #include <linux/errno.h>
  13. #include <linux/signal.h>
  14. #include <linux/sched.h>
  15. #include <linux/ioport.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/init.h>
  18. #include <linux/irq.h>
  19. #include <linux/bitops.h>
  20. #include <asm/io.h>
  21. #include <asm/delay.h>
  22. #include <asm/irq.h>
  23. #include <asm/irc-regs.h>
  24. #include <asm/mb93493-irqs.h>
  25. #include <asm/mb93493-regs.h>
  26. #define IRQ_ROUTE_ONE(X) (X##_ROUTE << (X - IRQ_BASE_MB93493))
  27. #define IRQ_ROUTING \
  28. (IRQ_ROUTE_ONE(IRQ_MB93493_VDC) | \
  29. IRQ_ROUTE_ONE(IRQ_MB93493_VCC) | \
  30. IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_OUT) | \
  31. IRQ_ROUTE_ONE(IRQ_MB93493_I2C_0) | \
  32. IRQ_ROUTE_ONE(IRQ_MB93493_I2C_1) | \
  33. IRQ_ROUTE_ONE(IRQ_MB93493_USB) | \
  34. IRQ_ROUTE_ONE(IRQ_MB93493_LOCAL_BUS) | \
  35. IRQ_ROUTE_ONE(IRQ_MB93493_PCMCIA) | \
  36. IRQ_ROUTE_ONE(IRQ_MB93493_GPIO) | \
  37. IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_IN))
  38. /*
  39. * daughter board PIC operations
  40. * - there is no way to ACK interrupts in the MB93493 chip
  41. */
  42. static void frv_mb93493_mask(struct irq_data *d)
  43. {
  44. uint32_t iqsr;
  45. volatile void *piqsr;
  46. if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
  47. piqsr = __addr_MB93493_IQSR(1);
  48. else
  49. piqsr = __addr_MB93493_IQSR(0);
  50. iqsr = readl(piqsr);
  51. iqsr &= ~(1 << (d->irq - IRQ_BASE_MB93493 + 16));
  52. writel(iqsr, piqsr);
  53. }
  54. static void frv_mb93493_ack(struct irq_data *d)
  55. {
  56. }
  57. static void frv_mb93493_unmask(struct irq_data *d)
  58. {
  59. uint32_t iqsr;
  60. volatile void *piqsr;
  61. if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
  62. piqsr = __addr_MB93493_IQSR(1);
  63. else
  64. piqsr = __addr_MB93493_IQSR(0);
  65. iqsr = readl(piqsr);
  66. iqsr |= 1 << (d->irq - IRQ_BASE_MB93493 + 16);
  67. writel(iqsr, piqsr);
  68. }
  69. static struct irq_chip frv_mb93493_pic = {
  70. .name = "mb93093",
  71. .irq_ack = frv_mb93493_ack,
  72. .irq_mask = frv_mb93493_mask,
  73. .irq_mask_ack = frv_mb93493_mask,
  74. .irq_unmask = frv_mb93493_unmask,
  75. };
  76. /*
  77. * MB93493 PIC interrupt handler
  78. */
  79. static irqreturn_t mb93493_interrupt(int irq, void *_piqsr)
  80. {
  81. volatile void *piqsr = _piqsr;
  82. uint32_t iqsr;
  83. iqsr = readl(piqsr);
  84. iqsr = iqsr & (iqsr >> 16) & 0xffff;
  85. /* poll all the triggered IRQs */
  86. while (iqsr) {
  87. int irq;
  88. asm("scan %1,gr0,%0" : "=r"(irq) : "r"(iqsr));
  89. irq = 31 - irq;
  90. iqsr &= ~(1 << irq);
  91. generic_handle_irq(IRQ_BASE_MB93493 + irq);
  92. }
  93. return IRQ_HANDLED;
  94. }
  95. /*
  96. * define an interrupt action for each MB93493 PIC output
  97. * - use dev_id to indicate the MB93493 PIC input to output mappings
  98. */
  99. static struct irqaction mb93493_irq[2] = {
  100. [0] = {
  101. .handler = mb93493_interrupt,
  102. .flags = IRQF_SHARED,
  103. .name = "mb93493.0",
  104. .dev_id = (void *) __addr_MB93493_IQSR(0),
  105. },
  106. [1] = {
  107. .handler = mb93493_interrupt,
  108. .flags = IRQF_SHARED,
  109. .name = "mb93493.1",
  110. .dev_id = (void *) __addr_MB93493_IQSR(1),
  111. }
  112. };
  113. /*
  114. * initialise the motherboard MB93493's PIC
  115. */
  116. void __init mb93493_init(void)
  117. {
  118. int irq;
  119. for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++)
  120. irq_set_chip_and_handler(irq, &frv_mb93493_pic,
  121. handle_edge_irq);
  122. /* the MB93493 drives external IRQ inputs on the CPU PIC */
  123. setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]);
  124. setup_irq(IRQ_CPU_MB93493_1, &mb93493_irq[1]);
  125. }