155 lines
4.9 KiB
C
155 lines
4.9 KiB
C
/***************************************************************************
|
|
* 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<<AT91C_ID_SYS);
|
|
}
|
|
|
|
void sysc_register_isr(enum syscirqs irq, SYSCISR *isr)
|
|
{
|
|
if (irq >= AT91_SYSIRQ_COUNT)
|
|
return;
|
|
|
|
sysc_isrs[irq] = isr;
|
|
}
|