@ -28,96 +28,101 @@
# include <asm/processor.h>
# include <commproc.h>
/**************************************************************************** /
/************************************************************************/
unsigned decrementer_count ; /* count value for 1e6/HZ microseconds */
/**************************************************************************** /
/************************************************************************/
/*
* CPM interrupt vector functions .
*/
struct cpm _action {
struct interrupt _action {
interrupt_handler_t * handler ;
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 ( 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 ;
asm volatile ( " mfmsr %0 " : " =r " ( msr ) : ) ;
asm volatile ( " mfmsr %0 " : " =r " ( 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 ;
asm volatile ( " mfdec %0 " : " =r " ( val ) : ) ;
asm volatile ( " mfdec %0 " : " =r " ( 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 )
{
set_msr ( get_msr ( ) | MSR_EE ) ;
set_msr ( get_msr ( ) | MSR_EE ) ;
}
/* returns flag if MSR_EE was set before */
int disable_interrupts ( void )
{
ulong msr = get_msr ( ) ;
ulong msr = get_msr ( ) ;
set_msr ( msr & ~ MSR_EE ) ;
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 */
immr - > im_siu_conf . sc_simask = 1 < < ( 31 - CPM_INTERRUPT ) ;
/* Configure CPM interrupts */
cpm_interrupt_init ( ) ;
set_dec ( decrementer_count ) ;
set_msr ( get_msr ( ) | MSR_EE ) ;
set_msr ( get_msr ( ) | MSR_EE ) ;
return ( 0 ) ;
}
/**************************************************************************** /
/************************************************************************/
/*
* 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 ;
ulong simask , newmask ;
ulong vec , v_bit ;
@ -139,6 +144,7 @@ void external_interrupt(struct pt_regs *regs)
if ( ! ( irq & 0x1 ) ) { /* External Interrupt ? */
ulong siel ;
/*
* Read Interrupt Edge / Level Register
*/
@ -152,33 +158,28 @@ void external_interrupt(struct pt_regs *regs)
}
}
switch ( irq ) {
case CPM_INTERRUPT :
cpm_interrupt ( irq , regs ) ;
break ;
default :
if ( irq_vecs [ irq ] . handler ! = NULL ) {
irq_vecs [ irq ] . handler ( irq_vecs [ irq ] . arg ) ;
} else {
printf ( " \n Bogus External Interrupt IRQ %d Vector %ld \n " ,
irq , vec ) ;
/* turn off the bogus interrupt to avoid it from now */
simask & = ~ v_bit ;
break ;
}
/*
* Re - Enable old Interrupt Mask
*/
immr - > im_siu_conf . sc_simask = simask ;
}
/**************************************************************************** /
/************************************************************************/
/*
* CPM interrupt handler
*/
static void
cpm_interrupt ( int irq , struct pt_regs * regs )
static void cpm_interrupt ( void * regs )
{
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
volatile immap_t * immr = ( immap_t * ) CFG_IMMR ;
uint vec ;
/*
@ -190,13 +191,14 @@ cpm_interrupt(int irq, struct pt_regs * regs)
vec > > = 11 ;
if ( cpm_vecs [ vec ] . handler ! = NULL ) {
( * cpm_vecs [ vec ] . handler ) ( cpm_vecs [ vec ] . arg ) ;
( * cpm_vecs [ vec ] . handler ) ( cpm_vecs [ vec ] . arg ) ;
} else {
immr - > im_cpic . cpic_cimr & = ~ ( 1 < < 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 ) ;
}
@ -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
* need any special tests in the interrupt handler .
*/
static void
cpm_error_interrupt ( void * dummy )
static void 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 * arg )
void 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 ) {
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 ] . arg = arg ;
immr - > im_cpic . cpic_cimr | = ( 1 < < vec ) ;
#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
} 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
irq_free_handler ( int vec )
void 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 ) ;
@ -246,36 +269,50 @@ irq_free_handler(int vec)
immr - > im_cpic . cpic_cimr & = ~ ( 1 < < vec ) ;
cpm_vecs [ vec ] . handler = 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
cpm_interrupt_init ( void )
static 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 .
*/
immr - > im_cpic . cpic_cicr =
( CICR_SCD_SCC4 |
( CICR_SCD_SCC4 |
CICR_SCC_SCC3 |
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 ;
/*
* 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 ;
/*
* Install the cpm interrupt handler
*/
irq_install_handler ( CPM_INTERRUPT , cpm_interrupt , NULL ) ;
}
/****************************************************************************/
/************************************************************************/
volatile ulong timestamp = 0 ;
@ -284,9 +321,10 @@ volatile ulong timestamp = 0;
* with interrupts disabled .
* 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
extern void status_led_tick ( ulong ) ;
# endif
@ -295,7 +333,7 @@ void timer_interrupt(struct pt_regs *regs)
# endif
/* Reset Timer Expired and Timers Interrupt Status */
immr - > im_clkrstk . cark_plprcrk = KAPWR_KEY ;
__asm__ ( " nop " ) ;
__asm__ ( " nop " ) ;
immr - > im_clkrst . car_plprcr | = PLPRCR_TEXPS | PLPRCR_TMIST ;
/* Restore Decrementer Count */
set_dec ( decrementer_count ) ;
@ -308,7 +346,6 @@ void timer_interrupt(struct pt_regs *regs)
# if defined(CONFIG_WATCHDOG) || defined(CFG_CMA_LCD_HEARTBEAT)
/*
* The shortest watchdog period of all boards ( except LWMON )
* is approx . 1 sec , thus re - trigger watchdog at least
@ -321,20 +358,20 @@ void timer_interrupt(struct pt_regs *regs)
# endif
# if defined(CFG_CMA_LCD_HEARTBEAT)
extern void lcd_heartbeat ( void ) ;
lcd_heartbeat ( ) ;
extern void lcd_heartbeat ( void ) ;
lcd_heartbeat ( ) ;
# endif /* CFG_CMA_LCD_HEARTBEAT */
# if defined(CONFIG_WATCHDOG)
reset_8xx_watchdog ( immr ) ;
reset_8xx_watchdog ( immr ) ;
# endif /* CONFIG_WATCHDOG */
}
# endif /* CONFIG_WATCHDOG || CFG_CMA_LCD_HEARTBEAT */
}
/**************************************************************************** /
/************************************************************************/
void reset_timer ( void )
{
@ -351,4 +388,4 @@ void set_timer (ulong t)
timestamp = t ;
}
/**************************************************************************** /
/************************************************************************/