@ -28,99 +28,104 @@
# 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 ;
}
}
static __inline__ void set_msr ( unsigned long msr )
static __inline__ void set_msr ( unsigned long msr )
{
{
asm volatile ( " mtmsr %0 " : : " r " ( msr ) ) ;
asm volatile ( " mtmsr %0 " : : " r " ( msr ) ) ;
}
}
static __inline__ unsigned long get_dec ( void )
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 ;
}
}
static __inline__ void set_dec ( unsigned long val )
static __inline__ void set_dec ( unsigned long val )
{
{
asm volatile ( " mtdec %0 " : : " r " ( val ) ) ;
asm volatile ( " mtdec %0 " : : " r " ( val ) ) ;
}
}
void enable_interrupts ( void )
void enable_interrupts ( void )
{
{
set_msr ( get_msr ( ) | MSR_EE ) ;
set_msr ( get_msr ( ) | MSR_EE ) ;
}
}
/* returns flag if MSR_EE was set before */
/* returns flag if MSR_EE was set before */
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 )
{
{
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
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 ) ;
set_msr ( get_msr ( ) | MSR_EE ) ;
set_msr ( get_msr ( ) | MSR_EE ) ;
return ( 0 ) ;
return ( 0 ) ;
}
}
/**************************************************************************** /
/************************************************************************/
/*
/*
* Handle external interrupts
* Handle external interrupts
*/
*/
void external_interrupt ( struct pt_regs * regs )
void external_interrupt ( struct pt_regs * regs )
{
{
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
int irq ;
int irq ;
ulong simask , newmask ;
ulong simask , newmask ;
ulong vec , v_bit ;
ulong vec , v_bit ;
/*
/*
* read the SIVEC register and shift the bits down
* read the SIVEC register and shift the bits down
@ -137,14 +142,15 @@ void external_interrupt(struct pt_regs *regs)
newmask = simask & ( ~ ( 0xFFFF0000 > > irq ) ) ;
newmask = simask & ( ~ ( 0xFFFF0000 > > irq ) ) ;
immr - > im_siu_conf . sc_simask = newmask ;
immr - > im_siu_conf . sc_simask = newmask ;
if ( ! ( irq & 0x1 ) ) { /* External Interrupt ? */
if ( ! ( irq & 0x1 ) ) { /* External Interrupt ? */
ulong siel ;
ulong siel ;
/*
/*
* Read Interrupt Edge / Level Register
* Read Interrupt Edge / Level Register
*/
*/
siel = immr - > im_siu_conf . sc_siel ;
siel = immr - > im_siu_conf . sc_siel ;
if ( siel & v_bit ) { /* edge triggered interrupt ? */
if ( siel & v_bit ) { /* edge triggered interrupt ? */
/*
/*
* Rewrite SIPEND Register to clear interrupt
* Rewrite SIPEND Register to clear interrupt
*/
*/
@ -152,34 +158,29 @@ 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 ;
/*
/*
* Get the vector by setting the ACK bit
* Get the vector by setting the ACK bit
@ -190,13 +191,14 @@ cpm_interrupt(int irq, struct pt_regs * regs)
vec > > = 11 ;
vec > > = 11 ;
if ( cpm_vecs [ vec ] . handler ! = NULL ) {
if ( cpm_vecs [ vec ] . handler ! = NULL ) {
( * cpm_vecs [ vec ] . handler ) ( cpm_vecs [ vec ] . arg ) ;
( * cpm_vecs [ vec ] . handler ) ( cpm_vecs [ vec ] . arg ) ;
} else {
} else {
immr - > im_cpic . cpic_cimr & = ~ ( 1 < < vec ) ;
immr - > im_cpic . cpic_cimr & = ~ ( 1 < < vec ) ;
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,75 +209,110 @@ 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 ( cpm_vecs [ vec ] . handler ! = NULL ) {
if ( ( vec & CPMVEC_OFFSET ) ! = 0 ) {
printf ( " CPM interrupt 0x%x replacing 0x%x \n " ,
/* CPM interrupt */
( uint ) handler , ( uint ) cpm_vecs [ vec ] . handler ) ;
vec & = 0xffff ;
}
if ( cpm_vecs [ vec ] . handler ! = NULL ) {
cpm_vecs [ vec ] . handler = handler ;
printf ( " CPM interrupt 0x%x replacing 0x%x \n " ,
cpm_vecs [ vec ] . arg = arg ;
( uint ) handler ,
immr - > im_cpic . cpic_cimr | = ( 1 < < vec ) ;
( uint ) cpm_vecs [ vec ] . handler ) ;
}
cpm_vecs [ vec ] . handler = handler ;
cpm_vecs [ vec ] . arg = arg ;
immr - > im_cpic . cpic_cimr | = ( 1 < < vec ) ;
#if 0
printf ( " Install CPM interrupt for vector %d ==> %p \n " ,
vec , handler ) ;
# 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
#if 0
printf ( " Install CPM interrupt for vector %d ==> %p \n " , vec , handler ) ;
printf ( " Install SIU interrupt for vector %d ==> %p \n " ,
vec , handler ) ;
# endif
# 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
printf ( " Free CPM interrupt for vector %d ==> %p \n " ,
vec , cpm_vecs [ vec ] . handler ) ;
# endif
immr - > im_cpic . cpic_cimr & = ~ ( 1 < < vec ) ;
cpm_vecs [ vec ] . handler = NULL ;
cpm_vecs [ vec ] . arg = NULL ;
} else {
/* SIU interrupt */
#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 ) ;
# endif
# endif
immr - > im_cpic . cpic_cimr & = ~ ( 1 < < vec ) ;
immr - > im_siu_conf . sc_simask & = ~ ( 1 < < ( 31 - vec ) ) ;
cpm_vecs [ vec ] . handler = NULL ;
irq_vecs [ vec ] . handler = NULL ;
cpm_vecs [ vec ] . arg = 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 ;
/*
/*
* Initialize the CPM interrupt controller .
* Initialize the CPM interrupt controller .
*/
*/
immr - > im_cpic . cpic_cicr =
immr - > im_cpic . cpic_cicr =
( CICR_SCD_SCC4 |
( CICR_SCD_SCC4 |
CICR_SCC_SCC3 |
CICR_SCC_SCC3 |
CICR_SCB_SCC2 |
CICR_SCB_SCC2 |
CICR_SCA_SCC1 ) | ( ( CPM_INTERRUPT / 2 ) < < 13 ) | CICR_HP_MASK ;
CICR_SCA_SCC1 ) | ( ( CPM_INTERRUPT / 2 ) < < 13 ) | CICR_HP_MASK ;
immr - > im_cpic . cpic_cimr = 0 ;
immr - > im_cpic . cpic_cimr = 0 ;
/*
/*
* Install the error handler .
* Install the error handler .
*/
*/
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 ;
@ -284,18 +321,19 @@ volatile ulong timestamp = 0;
* with interrupts disabled .
* with interrupts disabled .
* Trivial implementation - no need to be really accurate .
* Trivial implementation - no need to be really accurate .
*/
*/
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
#if 0
#if 0
printf ( " *** Timer Interrupt *** " ) ;
printf ( " *** Timer Interrupt *** " ) ;
# endif
# endif
/* Reset Timer Expired and Timers Interrupt Status */
/* Reset Timer Expired and Timers Interrupt Status */
immr - > im_clkrstk . cark_plprcrk = KAPWR_KEY ;
immr - > im_clkrstk . cark_plprcrk = KAPWR_KEY ;
__asm__ ( " nop " ) ;
__asm__ ( " nop " ) ;
immr - > im_clkrst . car_plprcr | = PLPRCR_TEXPS | PLPRCR_TMIST ;
immr - > im_clkrst . car_plprcr | = PLPRCR_TEXPS | PLPRCR_TMIST ;
/* Restore Decrementer Count */
/* Restore Decrementer Count */
set_dec ( decrementer_count ) ;
set_dec ( decrementer_count ) ;
@ -304,11 +342,10 @@ void timer_interrupt(struct pt_regs *regs)
# ifdef CONFIG_STATUS_LED
# ifdef CONFIG_STATUS_LED
status_led_tick ( timestamp ) ;
status_led_tick ( timestamp ) ;
# endif /* CONFIG_STATUS_LED */
# endif /* CONFIG_STATUS_LED */
# 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
@ -321,20 +358,20 @@ void timer_interrupt(struct pt_regs *regs)
# endif
# endif
# 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 */
# if defined(CONFIG_WATCHDOG)
# if defined(CONFIG_WATCHDOG)
reset_8xx_watchdog ( immr ) ;
reset_8xx_watchdog ( immr ) ;
# 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 ;
}
}
/**************************************************************************** /
/************************************************************************/