ih_at91pwmc.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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 2010/12/14 21:08:11 ve2yag
  36. * Take TC0 interrupt handler to create new PWMC handler.
  37. * priority set to 5.
  38. *
  39. * Revision 1.5 2008/08/11 06:59:11 haraldkipp
  40. * BSD types replaced by stdint types (feature request #1282721).
  41. *
  42. * Revision 1.4 2008/07/26 09:43:01 haraldkipp
  43. * Added support for retrieving and setting the interrupt mode.
  44. *
  45. * Revision 1.3 2006/09/29 12:36:48 haraldkipp
  46. * Default interrupt priority changed from 4 to 0. As this is typically used
  47. * by the system timer, lowest priority is fine.
  48. *
  49. * Revision 1.2 2006/06/28 17:10:27 haraldkipp
  50. * Include more general header file for ARM.
  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_PWMC
  59. #define NUT_IRQPRI_PWMC 5
  60. #endif
  61. static int PulseWidthModulatorIrqCtl(int cmd, void *param);
  62. IRQ_HANDLER sig_PWMC = {
  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. PulseWidthModulatorIrqCtl /* Interrupt control, ir_ctl. */
  69. };
  70. /*!
  71. * \brief pulse width modulator interrupt entry.
  72. */
  73. static unsigned int dummy;
  74. static void PulseWidthModulatorIrqEntry(void) NUT_NAKED_FUNC;
  75. void PulseWidthModulatorIrqEntry(void)
  76. {
  77. IRQ_ENTRY();
  78. #ifdef NUT_PERFMON
  79. sig_PWMC.ir_count++;
  80. #endif
  81. dummy = inr(PWMC_ISR);
  82. if (sig_PWMC.ir_handler) {
  83. (sig_PWMC.ir_handler) (sig_PWMC.ir_arg);
  84. }
  85. IRQ_EXIT();
  86. }
  87. /*!
  88. * \brief pulse width modulator 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 (NUT_IRQMODE_LEVEL or NUT_IRQMODE_EDGE).
  97. * - NUT_IRQCTL_GETPRIO Query interrupt priority.
  98. * - NUT_IRQCTL_SETPRIO Set interrupt priority.
  99. * - NUT_IRQCTL_GETCOUNT Query and clear interrupt counter.
  100. * \param param Pointer to optional parameter.
  101. *
  102. * \return 0 on success, -1 otherwise.
  103. */
  104. static int PulseWidthModulatorIrqCtl(int cmd, void *param)
  105. {
  106. int rc = 0;
  107. unsigned int *ival = (unsigned int *)param;
  108. int_fast8_t enabled = inr(AIC_IMR) & _BV(PWMC_ID);
  109. /* Disable interrupt. */
  110. if (enabled) {
  111. outr(AIC_IDCR, _BV(PWMC_ID));
  112. }
  113. switch(cmd) {
  114. case NUT_IRQCTL_INIT:
  115. /* Set the vector. */
  116. outr(AIC_SVR(PWMC_ID), (unsigned int)PulseWidthModulatorIrqEntry);
  117. /* Initialize to edge triggered with defined priority. */
  118. outr(AIC_SMR(PWMC_ID), AIC_SRCTYPE_EXT_HIGH_LEVEL | NUT_IRQPRI_PWMC);
  119. /* Clear interrupt */
  120. outr(AIC_ICCR, _BV(PWMC_ID));
  121. break;
  122. case NUT_IRQCTL_STATUS:
  123. if (enabled) {
  124. *ival |= 1;
  125. }
  126. else {
  127. *ival &= ~1;
  128. }
  129. break;
  130. case NUT_IRQCTL_ENABLE:
  131. enabled = 1;
  132. break;
  133. case NUT_IRQCTL_DISABLE:
  134. enabled = 0;
  135. break;
  136. case NUT_IRQCTL_GETMODE:
  137. {
  138. unsigned int val = inr(AIC_SMR(PWMC_ID)) & AIC_SRCTYPE;
  139. if (val == AIC_SRCTYPE_INT_LEVEL_SENSITIVE || val == AIC_SRCTYPE_EXT_HIGH_LEVEL) {
  140. *ival = NUT_IRQMODE_LEVEL;
  141. } else {
  142. *ival = NUT_IRQMODE_EDGE;
  143. }
  144. }
  145. break;
  146. case NUT_IRQCTL_SETMODE:
  147. if (*ival == NUT_IRQMODE_LEVEL) {
  148. outr(AIC_SMR(PWMC_ID), (inr(AIC_SMR(PWMC_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_INT_LEVEL_SENSITIVE);
  149. } else if (*ival == NUT_IRQMODE_EDGE) {
  150. outr(AIC_SMR(PWMC_ID), (inr(AIC_SMR(PWMC_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_INT_EDGE_TRIGGERED);
  151. } else {
  152. rc = -1;
  153. }
  154. break;
  155. case NUT_IRQCTL_GETPRIO:
  156. *ival = inr(AIC_SMR(PWMC_ID)) & AIC_PRIOR;
  157. break;
  158. case NUT_IRQCTL_SETPRIO:
  159. outr(AIC_SMR(PWMC_ID), (inr(AIC_SMR(PWMC_ID)) & ~AIC_PRIOR) | *ival);
  160. break;
  161. #ifdef NUT_PERFMON
  162. case NUT_IRQCTL_GETCOUNT:
  163. *ival = (unsigned int)sig_PWMC.ir_count;
  164. sig_PWMC.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(PWMC_ID));
  174. }
  175. return rc;
  176. }