@ -28,32 +28,34 @@
# include <asm/processor.h>
# include <asm/processor.h>
# include <commproc.h>
# include <commproc.h>
/**************************************************************************** /
/************************************************************************/
unsigned decrementer_count ; /* count value for 1e6/HZ microseconds */
unsigned decrementer_count ; /* count value for 1e6/HZ microseconds */
/**************************************************************************** /
/************************************************************************/
/*
/*
* CPM interrupt vector functions .
* CPM interrupt vector functions .
*/
*/
struct cpm _action {
struct interrupt _action {
interrupt_handler_t * handler ;
interrupt_handler_t * handler ;
void * arg ;
void * arg ;
} ;
} ;
static struct cpm_action cpm_vecs [ CPMVEC_NR ] ;
static struct interrupt_action cpm_vecs [ CPMVEC_NR ] ;
static struct interrupt_action irq_vecs [ NR_IRQS ] ;
static void cpm_interrupt_init ( void ) ;
static void cpm_interrupt_init ( void ) ;
static void cpm_interrupt ( int irq , struct pt_regs * regs ) ;
static void cpm_interrupt ( void * regs ) ;
/**************************************************************************** /
/************************************************************************/
static __inline__ unsigned long get_msr ( void )
static __inline__ unsigned long get_msr ( void )
{
{
unsigned long msr ;
unsigned long msr ;
asm volatile ( " mfmsr %0 " : " =r " ( msr ) : ) ;
asm volatile ( " mfmsr %0 " : " =r " ( msr ) : ) ;
return msr ;
return msr ;
}
}
@ -67,6 +69,7 @@ static __inline__ unsigned long get_dec(void)
unsigned long val ;
unsigned long val ;
asm volatile ( " mfdec %0 " : " =r " ( val ) : ) ;
asm volatile ( " mfdec %0 " : " =r " ( val ) : ) ;
return val ;
return val ;
}
}
@ -86,11 +89,12 @@ void enable_interrupts (void)
int disable_interrupts ( void )
int disable_interrupts ( void )
{
{
ulong msr = get_msr ( ) ;
ulong msr = get_msr ( ) ;
set_msr ( msr & ~ MSR_EE ) ;
set_msr ( msr & ~ MSR_EE ) ;
return ( ( msr & MSR_EE ) ! = 0 ) ;
return ( ( msr & MSR_EE ) ! = 0 ) ;
}
}
/**************************************************************************** /
/************************************************************************/
int interrupt_init ( void )
int interrupt_init ( void )
{
{
@ -98,10 +102,11 @@ int interrupt_init(void)
decrementer_count = get_tbclk ( ) / CFG_HZ ;
decrementer_count = get_tbclk ( ) / CFG_HZ ;
cpm_interrupt_init ( ) ;
/* disable all interrupts */
immr - > im_siu_conf . sc_simask = 0 ;
/* disable all interrupts except for the CPM interrupt */
/* Configure CPM interrupts */
immr - > im_siu_conf . sc_simask = 1 < < ( 31 - CPM_INTERRUPT ) ;
cpm_interrupt_init ( ) ;
set_dec ( decrementer_count ) ;
set_dec ( decrementer_count ) ;
@ -110,7 +115,7 @@ int interrupt_init(void)
return ( 0 ) ;
return ( 0 ) ;
}
}
/**************************************************************************** /
/************************************************************************/
/*
/*
* Handle external interrupts
* Handle external interrupts
@ -139,6 +144,7 @@ void external_interrupt(struct pt_regs *regs)
if ( ! ( irq & 0x1 ) ) { /* External Interrupt ? */
if ( ! ( irq & 0x1 ) ) { /* External Interrupt ? */
ulong siel ;
ulong siel ;
/*
/*
* Read Interrupt Edge / Level Register
* Read Interrupt Edge / Level Register
*/
*/
@ -152,31 +158,26 @@ void external_interrupt(struct pt_regs *regs)
}
}
}
}
switch ( irq ) {
if ( irq_vecs [ irq ] . handler ! = NULL ) {
case CPM_INTERRUPT :
irq_vecs [ irq ] . handler ( irq_vecs [ irq ] . arg ) ;
cpm_interrupt ( irq , regs ) ;
} else {
break ;
default :
printf ( " \n Bogus External Interrupt IRQ %d Vector %ld \n " ,
printf ( " \n Bogus External Interrupt IRQ %d Vector %ld \n " ,
irq , vec ) ;
irq , vec ) ;
/* turn off the bogus interrupt to avoid it from now */
/* turn off the bogus interrupt to avoid it from now */
simask & = ~ v_bit ;
simask & = ~ v_bit ;
break ;
}
}
/*
/*
* Re - Enable old Interrupt Mask
* Re - Enable old Interrupt Mask
*/
*/
immr - > im_siu_conf . sc_simask = simask ;
immr - > im_siu_conf . sc_simask = simask ;
}
}
/**************************************************************************** /
/************************************************************************/
/*
/*
* CPM interrupt handler
* CPM interrupt handler
*/
*/
static void
static void cpm_interrupt ( void * regs )
cpm_interrupt ( int irq , struct pt_regs * regs )
{
{
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
uint vec ;
uint vec ;
@ -196,7 +197,8 @@ cpm_interrupt(int irq, struct pt_regs * regs)
printf ( " Masking bogus CPM interrupt vector 0x%x \n " , vec ) ;
printf ( " Masking bogus CPM interrupt vector 0x%x \n " , vec ) ;
}
}
/*
/*
* After servicing the interrupt , we have to remove the status indicator .
* After servicing the interrupt ,
* we have to remove the status indicator .
*/
*/
immr - > im_cpic . cpic_cisr | = ( 1 < < vec ) ;
immr - > im_cpic . cpic_cisr | = ( 1 < < vec ) ;
}
}
@ -207,38 +209,59 @@ cpm_interrupt(int irq, struct pt_regs * regs)
* to do is ACK it and return . This is a no - op function so we don ' t
* to do is ACK it and return . This is a no - op function so we don ' t
* need any special tests in the interrupt handler .
* need any special tests in the interrupt handler .
*/
*/
static void
static void cpm_error_interrupt ( void * dummy )
cpm_error_interrupt ( void * dummy )
{
{
}
}
/****************************************************************************/
/************************************************************************/
/*
/*
* Install and free a CPM interrupt handler .
* Install and free an interrupt handler
*/
*/
void irq_install_handler ( int vec , interrupt_handler_t * handler ,
void
void * arg )
irq_install_handler ( int vec , interrupt_handler_t * handler , void * arg )
{
{
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
if ( ( vec & CPMVEC_OFFSET ) ! = 0 ) {
/* CPM interrupt */
vec & = 0xffff ;
if ( cpm_vecs [ vec ] . handler ! = NULL ) {
if ( cpm_vecs [ vec ] . handler ! = NULL ) {
printf ( " CPM interrupt 0x%x replacing 0x%x \n " ,
printf ( " CPM interrupt 0x%x replacing 0x%x \n " ,
( uint ) handler , ( uint ) cpm_vecs [ vec ] . handler ) ;
( uint ) handler ,
( uint ) cpm_vecs [ vec ] . handler ) ;
}
}
cpm_vecs [ vec ] . handler = handler ;
cpm_vecs [ vec ] . handler = handler ;
cpm_vecs [ vec ] . arg = arg ;
cpm_vecs [ vec ] . arg = arg ;
immr - > im_cpic . cpic_cimr | = ( 1 < < vec ) ;
immr - > im_cpic . cpic_cimr | = ( 1 < < vec ) ;
#if 0
#if 0
printf ( " Install CPM interrupt for vector %d ==> %p \n " , vec , handler ) ;
printf ( " Install CPM interrupt for vector %d ==> %p \n " ,
vec , handler ) ;
# endif
# endif
} else {
/* SIU interrupt */
if ( irq_vecs [ vec ] . handler ! = NULL ) {
printf ( " SIU interrupt %d 0x%x replacing 0x%x \n " ,
vec ,
( uint ) handler ,
( uint ) cpm_vecs [ vec ] . handler ) ;
}
irq_vecs [ vec ] . handler = handler ;
irq_vecs [ vec ] . arg = arg ;
immr - > im_siu_conf . sc_simask | = 1 < < ( 31 - vec ) ;
#if 0
printf ( " Install SIU interrupt for vector %d ==> %p \n " ,
vec , handler ) ;
# endif
}
}
}
void
void irq_free_handler ( int vec )
irq_free_handler ( int vec )
{
{
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
if ( ( vec & CPMVEC_OFFSET ) ! = 0 ) {
/* CPM interrupt */
vec & = 0xffff ;
#if 0
#if 0
printf ( " Free CPM interrupt for vector %d ==> %p \n " ,
printf ( " Free CPM interrupt for vector %d ==> %p \n " ,
vec , cpm_vecs [ vec ] . handler ) ;
vec , cpm_vecs [ vec ] . handler ) ;
@ -246,12 +269,21 @@ irq_free_handler(int vec)
immr - > im_cpic . cpic_cimr & = ~ ( 1 < < vec ) ;
immr - > im_cpic . cpic_cimr & = ~ ( 1 < < vec ) ;
cpm_vecs [ vec ] . handler = NULL ;
cpm_vecs [ vec ] . handler = NULL ;
cpm_vecs [ vec ] . arg = NULL ;
cpm_vecs [ vec ] . arg = NULL ;
} else {
/* SIU interrupt */
#if 0
printf ( " Free CPM interrupt for vector %d ==> %p \n " ,
vec , cpm_vecs [ vec ] . handler ) ;
# endif
immr - > im_siu_conf . sc_simask & = ~ ( 1 < < ( 31 - vec ) ) ;
irq_vecs [ vec ] . handler = NULL ;
irq_vecs [ vec ] . arg = NULL ;
}
}
}
/****************************************************************************/
/************************************************************************/
static void
static void cpm_interrupt_init ( void )
cpm_interrupt_init ( void )
{
{
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
@ -273,9 +305,14 @@ cpm_interrupt_init (void)
irq_install_handler ( CPMVEC_ERROR , cpm_error_interrupt , NULL ) ;
irq_install_handler ( CPMVEC_ERROR , cpm_error_interrupt , NULL ) ;
immr - > im_cpic . cpic_cicr | = CICR_IEN ;
immr - > im_cpic . cpic_cicr | = CICR_IEN ;
/*
* Install the cpm interrupt handler
*/
irq_install_handler ( CPM_INTERRUPT , cpm_interrupt , NULL ) ;
}
}
/****************************************************************************/
/************************************************************************/
volatile ulong timestamp = 0 ;
volatile ulong timestamp = 0 ;
@ -287,6 +324,7 @@ volatile ulong timestamp = 0;
void timer_interrupt ( struct pt_regs * regs )
void timer_interrupt ( struct pt_regs * regs )
{
{
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
# ifdef CONFIG_STATUS_LED
# ifdef CONFIG_STATUS_LED
extern void status_led_tick ( ulong ) ;
extern void status_led_tick ( ulong ) ;
# endif
# endif
@ -308,7 +346,6 @@ void timer_interrupt(struct pt_regs *regs)
# if defined(CONFIG_WATCHDOG) || defined(CFG_CMA_LCD_HEARTBEAT)
# if defined(CONFIG_WATCHDOG) || defined(CFG_CMA_LCD_HEARTBEAT)
/*
/*
* The shortest watchdog period of all boards ( except LWMON )
* The shortest watchdog period of all boards ( except LWMON )
* is approx . 1 sec , thus re - trigger watchdog at least
* is approx . 1 sec , thus re - trigger watchdog at least
@ -322,6 +359,7 @@ void timer_interrupt(struct pt_regs *regs)
# if defined(CFG_CMA_LCD_HEARTBEAT)
# if defined(CFG_CMA_LCD_HEARTBEAT)
extern void lcd_heartbeat ( void ) ;
extern void lcd_heartbeat ( void ) ;
lcd_heartbeat ( ) ;
lcd_heartbeat ( ) ;
# endif /* CFG_CMA_LCD_HEARTBEAT */
# endif /* CFG_CMA_LCD_HEARTBEAT */
@ -330,11 +368,10 @@ void timer_interrupt(struct pt_regs *regs)
# endif /* CONFIG_WATCHDOG */
# endif /* CONFIG_WATCHDOG */
}
}
# endif /* CONFIG_WATCHDOG || CFG_CMA_LCD_HEARTBEAT */
# endif /* CONFIG_WATCHDOG || CFG_CMA_LCD_HEARTBEAT */
}
}
/**************************************************************************** /
/************************************************************************/
void reset_timer ( void )
void reset_timer ( void )
{
{
@ -351,4 +388,4 @@ void set_timer (ulong t)
timestamp = t ;
timestamp = t ;
}
}
/**************************************************************************** /
/************************************************************************/