2009-06-12 22:01:00 +08:00
/*
* arch / score / kernel / irq . c
*
* Score Processor version .
*
* Copyright ( C ) 2009 Sunplus Core Technology Co . , Ltd .
* Chen Liqin < liqin . chen @ sunplusct . com >
* Lennox Wu < lennox . wu @ sunplusct . com >
*
* 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 ; either version 2 of the License , or
* ( at your option ) any later version .
*
* 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 , see the file COPYING , or write
* to the Free Software Foundation , Inc . ,
* 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# include <linux/interrupt.h>
# include <linux/kernel_stat.h>
# include <linux/seq_file.h>
# include <asm/io.h>
2009-06-27 15:22:00 +02:00
/* the interrupt controller is hardcoded at this address */
# define SCORE_PIC ((u32 __iomem __force *)0x95F50000)
# define INT_PNDL 0
# define INT_PNDH 1
# define INT_PRIORITY_M 2
# define INT_PRIORITY_SG0 4
# define INT_PRIORITY_SG1 5
# define INT_PRIORITY_SG2 6
# define INT_PRIORITY_SG3 7
# define INT_MASKL 8
# define INT_MASKH 9
2009-06-12 22:01:00 +08:00
/*
* handles all normal device IRQs
*/
asmlinkage void do_IRQ ( int irq )
{
irq_enter ( ) ;
generic_handle_irq ( irq ) ;
irq_exit ( ) ;
}
2011-02-06 22:23:47 +00:00
static void score_mask ( struct irq_data * d )
2009-06-12 22:01:00 +08:00
{
2011-02-06 22:23:47 +00:00
unsigned int irq_source = 63 - d - > irq ;
2009-06-12 22:01:00 +08:00
if ( irq_source < 32 )
2009-06-27 15:22:00 +02:00
__raw_writel ( ( __raw_readl ( SCORE_PIC + INT_MASKL ) | \
( 1 < < irq_source ) ) , SCORE_PIC + INT_MASKL ) ;
2009-06-12 22:01:00 +08:00
else
2009-06-27 15:22:00 +02:00
__raw_writel ( ( __raw_readl ( SCORE_PIC + INT_MASKH ) | \
( 1 < < ( irq_source - 32 ) ) ) , SCORE_PIC + INT_MASKH ) ;
2009-06-12 22:01:00 +08:00
}
2011-02-06 22:23:47 +00:00
static void score_unmask ( struct irq_data * d )
2009-06-12 22:01:00 +08:00
{
2011-02-06 22:23:47 +00:00
unsigned int irq_source = 63 - d - > irq ;
2009-06-12 22:01:00 +08:00
if ( irq_source < 32 )
2009-06-27 15:22:00 +02:00
__raw_writel ( ( __raw_readl ( SCORE_PIC + INT_MASKL ) & \
~ ( 1 < < irq_source ) ) , SCORE_PIC + INT_MASKL ) ;
2009-06-12 22:01:00 +08:00
else
2009-06-27 15:22:00 +02:00
__raw_writel ( ( __raw_readl ( SCORE_PIC + INT_MASKH ) & \
~ ( 1 < < ( irq_source - 32 ) ) ) , SCORE_PIC + INT_MASKH ) ;
2009-06-12 22:01:00 +08:00
}
struct irq_chip score_irq_chip = {
. name = " Score7-level " ,
2011-02-06 22:23:47 +00:00
. irq_mask = score_mask ,
. irq_mask_ack = score_mask ,
. irq_unmask = score_unmask ,
2009-06-12 22:01:00 +08:00
} ;
/*
* initialise the interrupt system
*/
void __init init_IRQ ( void )
{
int index ;
unsigned long target_addr ;
for ( index = 0 ; index < NR_IRQS ; + + index )
set_irq_chip_and_handler ( index , & score_irq_chip ,
handle_level_irq ) ;
for ( target_addr = IRQ_VECTOR_BASE_ADDR ;
target_addr < = IRQ_VECTOR_END_ADDR ;
target_addr + = IRQ_VECTOR_SIZE )
memcpy ( ( void * ) target_addr , \
interrupt_exception_vector , IRQ_VECTOR_SIZE ) ;
2009-06-27 15:22:00 +02:00
__raw_writel ( 0xffffffff , SCORE_PIC + INT_MASKL ) ;
__raw_writel ( 0xffffffff , SCORE_PIC + INT_MASKH ) ;
2009-06-12 22:01:00 +08:00
__asm__ __volatile__ (
" mtcr %0, cr3 \n \t "
: : " r " ( EXCEPTION_VECTOR_BASE_ADDR | \
VECTOR_ADDRESS_OFFSET_MODE16 ) ) ;
}
/*
* Generic , controller - independent functions :
*/
int show_interrupts ( struct seq_file * p , void * v )
{
int i = * ( loff_t * ) v , cpu ;
struct irqaction * action ;
unsigned long flags ;
if ( i = = 0 ) {
seq_puts ( p , " " ) ;
for_each_online_cpu ( cpu )
seq_printf ( p , " CPU%d " , cpu ) ;
seq_putc ( p , ' \n ' ) ;
}
if ( i < NR_IRQS ) {
2011-02-06 22:23:47 +00:00
struct irq_desc * desc = irq_to_desc ( i ) ;
raw_spin_lock_irqsave ( & desc - > lock , flags ) ;
action = desc - > action ;
2009-06-12 22:01:00 +08:00
if ( ! action )
goto unlock ;
seq_printf ( p , " %3d: " , i ) ;
seq_printf ( p , " %10u " , kstat_irqs ( i ) ) ;
2011-02-06 22:23:47 +00:00
seq_printf ( p , " %8s " , get_irq_desc_chip ( desc ) - > name ? : " - " ) ;
2009-06-12 22:01:00 +08:00
seq_printf ( p , " %s " , action - > name ) ;
for ( action = action - > next ; action ; action = action - > next )
seq_printf ( p , " , %s " , action - > name ) ;
seq_putc ( p , ' \n ' ) ;
unlock :
2011-02-06 22:23:47 +00:00
raw_spin_unlock_irqrestore ( & desc - > lock , flags ) ;
2009-06-12 22:01:00 +08:00
}
return 0 ;
}