/*************************************************************************** * sam7fc - System Interrupt Dispatcher * * * * Copyright (C) 01/2008 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; version 2 of the License * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "AT91SAM7S256.h" #include "at91_sysc.h" #include "board.h" static SYSCISR *sysc_isrs[AT91_SYSIRQ_COUNT]; struct _irq_regs { AT91_REG *mask_register; uint32_t mask; AT91_REG *status_register; uint32_t status; }; /* same IDs as sysc_isrs enum! */ static const struct _irq_regs irq_regs[] = { /* * PIT (Periodic Intervall Timer) * ISR must read AT91C_PITC_PIVR to clear interrupt * - PITIEN (Periodic Intervall Timer Interrupt Enable) */ { AT91C_PITC_PIMR, AT91C_PITC_PITIEN, AT91C_PITC_PISR, AT91C_PITC_PITS }, /* * DBGU (Debug Unit) * TODO: must use AT91C_DBGU_IDR to fault disable interrupt * - 12 Interrupt sources */ { AT91C_DBGU_IMR, (AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_ENDRX | AT91C_US_ENDTX | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_TXEMPTY | AT91C_US_TXBUFE | AT91C_US_RXBUFF | AT91C_US_COMM_TX | AT91C_US_COMM_RX), AT91C_DBGU_CSR, (AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_ENDRX | AT91C_US_ENDTX | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_TXEMPTY | AT91C_US_TXBUFE | AT91C_US_RXBUFF | AT91C_US_COMM_TX | AT91C_US_COMM_RX) }, /* * EFC (Embedded Flash Controller / Memory Controller) */ { AT91C_MC_FMR, (AT91C_MC_FRDY | AT91C_MC_LOCKE | AT91C_MC_PROGE), AT91C_MC_FSR, (AT91C_MC_FRDY | AT91C_MC_LOCKE | AT91C_MC_PROGE) }, /* * WDT (Watchdog Timer) * WDMR can be written only once (no fault disable) * - WDFIEN (Watchdog Fault Interrupt Enable) */ { AT91C_WDTC_WDMR, AT91C_WDTC_WDFIEN, AT91C_WDTC_WDSR, (AT91C_WDTC_WDUNF | AT91C_WDTC_WDERR) }, /* * RTT (Real-Time Timer) * Interrupts must be disabled during ISR?! * - ALMIEN (Alarm Interrupt Enable) * - RTTCINCIEN (Real-Time Timer Increment Interrupt Enable) */ { AT91C_RTTC_RTMR, (AT91C_RTTC_ALMIEN | AT91C_RTTC_RTTINCIEN), AT91C_RTTC_RTSR, (AT91C_RTTC_ALMS | AT91C_RTTC_RTTINC) }, /* * RSTC (Reset Controller) * - AT91C_RSTC_URSTIEN (User Reset Interrupt Enable) * - AT91C_RSTC_BODIEN (Brownout Detection Interrupt Enable) */ { AT91C_RSTC_RMR, (AT91C_RSTC_URSTIEN | AT91C_RSTC_BODIEN), AT91C_RSTC_RSR, (AT91C_RSTC_URSTS | AT91C_RSTC_BODSTS) }, /* * PMC (Power Managment Controller) * TODO: must use AT91C_PMC_IDR to fault disable interrupt * - 6 Interrupt sources */ { AT91C_PMC_IMR, (AT91C_PMC_MOSCS | AT91C_PMC_LOCK | AT91C_PMC_MCKRDY | AT91C_PMC_PCK0RDY | AT91C_PMC_PCK1RDY | AT91C_PMC_PCK2RDY), AT91C_PMC_SR, (AT91C_PMC_MOSCS | AT91C_PMC_LOCK | AT91C_PMC_MCKRDY | AT91C_PMC_PCK0RDY | AT91C_PMC_PCK1RDY | AT91C_PMC_PCK2RDY) }, }; /* check Interrupts from internal hardware */ static void at91_sysc_isr(void) { uint32_t id; for (id = 0; id < AT91_SYSIRQ_COUNT; id++) { /* check if interrups are enabled */ if (*(irq_regs[id].mask_register) & irq_regs[id].mask) { /* check if interrupts are active */ uint32_t status = *(irq_regs[id].status_register); if (status & irq_regs[id].status) { /* execute handler */ if (sysc_isrs[id]) { sysc_isrs[id](status); } else { /* disable interrupts */ *(irq_regs[id].mask_register) &= ~irq_regs[id].mask; } } } } } void at91_sysc_init(void) { /* high priority, level triggered, own vector */ AT91S_AIC *aic = AT91C_BASE_AIC; aic->AIC_SMR[AT91C_ID_SYS] = IRQPRIO_SYSC | AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL; aic->AIC_SVR[AT91C_ID_SYS] = (uint32_t)at91_sysc_isr; aic->AIC_IECR = (1<= AT91_SYSIRQ_COUNT) return; sysc_isrs[irq] = isr; }