ih_at91fiq.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright (C) 2005 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. /*
  34. * $Log$
  35. * Revision 1.6 2009/01/30 08:55:23 haraldkipp
  36. * Enable IRQ clocks.
  37. *
  38. * Revision 1.5 2008/08/11 06:59:09 haraldkipp
  39. * BSD types replaced by stdint types (feature request #1282721).
  40. *
  41. * Revision 1.4 2008/07/26 09:43:01 haraldkipp
  42. * Added support for retrieving and setting the interrupt mode.
  43. *
  44. * Revision 1.3 2006/06/28 17:10:15 haraldkipp
  45. * Include more general header file for ARM.
  46. *
  47. * Revision 1.2 2006/04/07 12:19:51 haraldkipp
  48. * Fast interrupts are now enabled correctly.
  49. * Mode set/get ioctl added and priority set/get removed.
  50. * Interrupt entry will no longer push R8-R12 on stack.
  51. *
  52. * Revision 1.1 2005/10/24 08:56:09 haraldkipp
  53. * First check in.
  54. *
  55. */
  56. #include <arch/arm.h>
  57. #include <dev/irqreg.h>
  58. #ifndef NUT_IRQPRI_FIQ
  59. #define NUT_IRQPRI_FIQ 4
  60. #endif
  61. static int FastIrqCtl(int cmd, void *param);
  62. IRQ_HANDLER sig_FIQ = {
  63. #ifdef NUT_PERFMON
  64. 0, /* Interrupt counter, ir_count. */
  65. #endif
  66. NULL, /* Passed argument, ir_arg. */
  67. NULL, /* Handler subroutine, ir_handler. */
  68. FastIrqCtl /* Interrupt control, ir_ctl. */
  69. };
  70. /*!
  71. * \brief Fast interrupt entry.
  72. *
  73. * \todo Use different entry/exit sequence for the fast interrupt.
  74. */
  75. static void FastIrqEntry(void) NUT_NAKED_FUNC;
  76. void FastIrqEntry(void)
  77. {
  78. FIQ_ENTRY();
  79. #ifdef NUT_PERFMON
  80. sig_FIQ.ir_count++;
  81. #endif
  82. if (sig_FIQ.ir_handler) {
  83. (sig_FIQ.ir_handler) (sig_FIQ.ir_arg);
  84. }
  85. FIQ_EXIT();
  86. }
  87. /*!
  88. * \brief Fast interrupt control.
  89. *
  90. * \param cmd Control command.
  91. * - NUT_IRQCTL_INIT Initialize and disable interrupt.
  92. * - NUT_IRQCTL_STATUS Query interrupt status.
  93. * - NUT_IRQCTL_ENABLE Enable interrupt.
  94. * - NUT_IRQCTL_DISABLE Disable interrupt.
  95. * - NUT_IRQCTL_GETMODE Query interrupt mode.
  96. * - NUT_IRQCTL_SETMODE Set interrupt mode.
  97. * - NUT_IRQCTL_GETCOUNT Query and clear interrupt counter.
  98. * \param param Pointer to optional parameter.
  99. *
  100. * \return 0 on success, -1 otherwise.
  101. */
  102. static int FastIrqCtl(int cmd, void *param)
  103. {
  104. int rc = 0;
  105. unsigned int *ival = (unsigned int *)param;
  106. int_fast8_t enabled = inr(AIC_IMR) & _BV(FIQ_ID);
  107. /* Disable interrupt. */
  108. if (enabled) {
  109. outr(AIC_IDCR, _BV(FIQ_ID));
  110. }
  111. switch(cmd) {
  112. case NUT_IRQCTL_INIT:
  113. /* Set the vector. */
  114. outr(AIC_SVR(FIQ_ID), (unsigned int)FastIrqEntry);
  115. /* Initialize to edge triggered with defined priority. */
  116. outr(AIC_SMR(FIQ_ID), AIC_SRCTYPE_EXT_NEGATIVE_EDGE | NUT_IRQPRI_FIQ);
  117. /* Clear interrupt */
  118. outr(AIC_ICCR, _BV(FIQ_ID));
  119. break;
  120. case NUT_IRQCTL_STATUS:
  121. if (enabled) {
  122. *ival |= 1;
  123. }
  124. else {
  125. *ival &= ~1;
  126. }
  127. break;
  128. case NUT_IRQCTL_ENABLE:
  129. enabled = 1;
  130. break;
  131. case NUT_IRQCTL_DISABLE:
  132. enabled = 0;
  133. break;
  134. case NUT_IRQCTL_GETMODE:
  135. {
  136. unsigned int val = inr(AIC_SMR(FIQ_ID)) & AIC_SRCTYPE;
  137. if (val == AIC_SRCTYPE_EXT_LOW_LEVEL) {
  138. *ival = NUT_IRQMODE_LOWLEVEL;
  139. } else if (val == AIC_SRCTYPE_EXT_HIGH_LEVEL) {
  140. *ival = NUT_IRQMODE_HIGHLEVEL;
  141. } else if (val == AIC_SRCTYPE_EXT_POSITIVE_EDGE) {
  142. *ival = NUT_IRQMODE_RISINGEDGE;
  143. } else {
  144. *ival = NUT_IRQMODE_FALLINGEDGE;
  145. }
  146. }
  147. break;
  148. case NUT_IRQCTL_SETMODE:
  149. if (*ival == NUT_IRQMODE_LOWLEVEL) {
  150. outr(AIC_SMR(FIQ_ID), (inr(AIC_SMR(FIQ_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_EXT_LOW_LEVEL);
  151. } else if (*ival == NUT_IRQMODE_HIGHLEVEL) {
  152. outr(AIC_SMR(FIQ_ID), (inr(AIC_SMR(FIQ_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_EXT_HIGH_LEVEL);
  153. } else if (*ival == NUT_IRQMODE_FALLINGEDGE) {
  154. outr(AIC_SMR(FIQ_ID), (inr(AIC_SMR(FIQ_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_EXT_NEGATIVE_EDGE);
  155. } else if (*ival == NUT_IRQMODE_RISINGEDGE) {
  156. outr(AIC_SMR(FIQ_ID), (inr(AIC_SMR(FIQ_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_EXT_POSITIVE_EDGE);
  157. } else {
  158. rc = -1;
  159. }
  160. break;
  161. #ifdef NUT_PERFMON
  162. case NUT_IRQCTL_GETCOUNT:
  163. *ival = (unsigned int)sig_FIQ.ir_count;
  164. sig_FIQ.ir_count = 0;
  165. break;
  166. #endif
  167. default:
  168. rc = -1;
  169. break;
  170. }
  171. /* Enable interrupt. */
  172. if (enabled) {
  173. outr(AIC_IECR, _BV(FIQ_ID));
  174. #if defined(PMC_PCER)
  175. outr(PMC_PCER, _BV(FIQ_ID));
  176. #endif
  177. }
  178. return rc;
  179. }