ih_at91sys.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log: ih_at91sys.c,v $
00036  * Revision 1.1  2007/02/15 16:11:14  haraldkipp
00037  * Support for system controller interrupts added.
00038  *
00039  */
00040 
00041 #include <arch/arm.h>
00042 #include <dev/irqreg.h>
00043 
00044 #ifndef NUT_IRQPRI_SYS
00045 #define NUT_IRQPRI_SYS  0
00046 #endif
00047 
00048 SYSIRQ_HANDLER syssig_DBGU;
00049 SYSIRQ_HANDLER syssig_MC;
00050 SYSIRQ_HANDLER syssig_PIT;
00051 SYSIRQ_HANDLER syssig_PMC;
00052 SYSIRQ_HANDLER syssig_RSTC;
00053 SYSIRQ_HANDLER syssig_RTT;
00054 SYSIRQ_HANDLER syssig_WDT;
00055 
00056 
00057 static int SystemIrqCtl(int cmd, void *param);
00058 
00059 IRQ_HANDLER sig_SYS = {
00060 #ifdef NUT_PERFMON
00061     0,                  /* Interrupt counter, ir_count. */
00062 #endif
00063     NULL,               /* Passed argument, ir_arg. */
00064     NULL,               /* Handler subroutine, ir_handler. */
00065     SystemIrqCtl /* Interrupt control, ir_ctl. */
00066 };
00067 
00071 static void SystemIrqEntry(void) __attribute__ ((naked));
00072 void SystemIrqEntry(void)
00073 {
00074     IRQ_ENTRY();
00075 #ifdef NUT_PERFMON
00076     sig_SYS.ir_count++;
00077 #endif
00078     if (syssig_DBGU.sir_enabled && syssig_DBGU.sir_handler) {
00079         /* Call debug unit interrupt handler. */
00080         (syssig_DBGU.sir_handler) (syssig_DBGU.sir_arg);
00081     }
00082     if (syssig_MC.sir_enabled && syssig_MC.sir_handler) {
00083         /* Call memory controller interrupt handler. */
00084         (syssig_MC.sir_handler) (syssig_MC.sir_arg);
00085     }
00086     if ((inr(PIT_MR) & PIT_PITIEN) != 0 && (inr(PIT_SR) & PIT_PITS) != 0) {
00087         if (syssig_PIT.sir_handler) {
00088             /* Call periodic interval timer interrupt handler. */
00089             (syssig_PIT.sir_handler) (syssig_PIT.sir_arg);
00090         }
00091         inr(PIT_PIVR);
00092     }
00093     if (syssig_PMC.sir_enabled && syssig_PMC.sir_handler) {
00094         /* Call power management controller interrupt handler. */
00095         (syssig_PMC.sir_handler) (syssig_PMC.sir_arg);
00096     }
00097     if (syssig_RSTC.sir_enabled && syssig_RSTC.sir_handler) {
00098         /* Call reset controller interrupt handler. */
00099         (syssig_RSTC.sir_handler) (syssig_RSTC.sir_arg);
00100     }
00101     if (syssig_RTT.sir_enabled && syssig_RTT.sir_handler) {
00102         /* Call real-time timer interrupt handler. */
00103         (syssig_RTT.sir_handler) (syssig_RTT.sir_arg);
00104     }
00105     if (syssig_WDT.sir_enabled && syssig_WDT.sir_handler) {
00106         /* Call watchdog timer interrupt handler. */
00107         (syssig_WDT.sir_handler) (syssig_WDT.sir_arg);
00108     }
00109     IRQ_EXIT();
00110 }
00111 
00127 static int SystemIrqCtl(int cmd, void *param)
00128 {
00129     int rc = 0;
00130     u_int *ival = (u_int *)param;
00131     int enabled = inr(AIC_IMR) & _BV(SYSC_ID);
00132 
00133     /* Disable interrupt. */
00134     if (enabled) {
00135         outr(AIC_IDCR, _BV(SYSC_ID));
00136     }
00137 
00138     switch(cmd) {
00139     case NUT_IRQCTL_INIT:
00140         /* Set the vector. */
00141         outr(AIC_SVR(SYSC_ID), (unsigned int)SystemIrqEntry);
00142         /* Initialize to edge triggered with defined priority. */
00143         outr(AIC_SMR(SYSC_ID), AIC_SRCTYPE_INT_EDGE_TRIGGERED | NUT_IRQPRI_SYS);
00144         /* Clear interrupt */
00145         outr(AIC_ICCR, _BV(SYSC_ID));
00146         break;
00147     case NUT_IRQCTL_STATUS:
00148         if (enabled) {
00149             *ival |= 1;
00150         }
00151         else {
00152             *ival &= ~1;
00153         }
00154         break;
00155     case NUT_IRQCTL_ENABLE:
00156         enabled = 1;
00157         break;
00158     case NUT_IRQCTL_DISABLE:
00159         enabled = 0;
00160         break;
00161     case NUT_IRQCTL_GETPRIO:
00162         *ival = inr(AIC_SMR(SYSC_ID)) & AIC_PRIOR;
00163         break;
00164     case NUT_IRQCTL_SETPRIO:
00165         outr(AIC_SMR(SYSC_ID), (inr(AIC_SMR(SYSC_ID)) & ~AIC_PRIOR) | *ival);
00166         break;
00167 #ifdef NUT_PERFMON
00168     case NUT_IRQCTL_GETCOUNT:
00169         *ival = (u_int)sig_SYS.ir_count;
00170         sig_SYS.ir_count = 0;
00171         break;
00172 #endif
00173     default:
00174         rc = -1;
00175         break;
00176     }
00177 
00178     /* Enable interrupt. */
00179     if (enabled) {
00180         outr(AIC_IECR, _BV(SYSC_ID));
00181     }
00182     return rc;
00183 }
00184 
00192 int NutSysIrqEnable(SYSIRQ_HANDLER * sysirq)
00193 {
00194     sysirq->sir_enabled = 1;
00195 
00196     return SystemIrqCtl(NUT_IRQCTL_ENABLE, NULL);
00197 }
00198 
00206 int NutSysIrqDisable(SYSIRQ_HANDLER * sysirq)
00207 {
00208     sysirq->sir_enabled = 0;
00209 
00210     return 0;
00211 }
00212 
00232 int NutRegisterSysIrqHandler(SYSIRQ_HANDLER * sysirq, void (*handler) (void *), void *arg)
00233 {
00234     int rc;
00235 
00236     /* Disable any previously registered handler. */
00237     NutSysIrqDisable(sysirq);
00238 
00239     /* Initialize this interrupt. */
00240     rc = SystemIrqCtl(NUT_IRQCTL_INIT, NULL);
00241 
00242     if (rc == 0) {
00243         /* Set the interrupt handler. */
00244         sysirq->sir_arg = arg;
00245         sysirq->sir_handler = handler;
00246     }
00247     return rc;
00248 }

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/