2006-01-16 22:14:14 -08:00
/*
* arch / sh / kernel / cpu / irq / imask . c
2005-04-16 15:20:36 -07:00
*
* Copyright ( C ) 1999 , 2000 Niibe Yutaka
*
* Simple interrupt handling using IMASK of SR register .
*
*/
/* NOTE: Will not work on level 15 */
# include <linux/ptrace.h>
# include <linux/errno.h>
# include <linux/kernel_stat.h>
# include <linux/signal.h>
# include <linux/sched.h>
# include <linux/interrupt.h>
# include <linux/init.h>
# include <linux/bitops.h>
# include <linux/spinlock.h>
# include <linux/cache.h>
# include <linux/irq.h>
2009-05-22 01:16:17 +09:00
# include <linux/bitmap.h>
2006-01-16 22:14:14 -08:00
# include <asm/irq.h>
2005-04-16 15:20:36 -07:00
/* Bitmap of IRQ masked */
# define IMASK_PRIORITY 15
2009-05-22 01:16:17 +09:00
static DECLARE_BITMAP ( imask_mask , IMASK_PRIORITY ) ;
static int interrupt_priority ;
2005-04-16 15:20:36 -07:00
2009-05-22 01:16:17 +09:00
static inline void set_interrupt_registers ( int ip )
2005-04-16 15:20:36 -07:00
{
unsigned long __dummy ;
2006-11-05 15:40:13 +09:00
asm volatile (
# ifdef CONFIG_CPU_HAS_SR_RB
" ldc %2, r6_bank \n \t "
# endif
2005-04-16 15:20:36 -07:00
" stc sr, %0 \n \t "
" and #0xf0, %0 \n \t "
" shlr2 %0 \n \t "
" cmp/eq #0x3c, %0 \n \t "
" bt/s 1f ! CLI-ed \n \t "
" stc sr, %0 \n \t "
" and %1, %0 \n \t "
" or %2, %0 \n \t "
" ldc %0, sr \n "
" 1: "
: " =&z " ( __dummy )
: " r " ( ~ 0xf0 ) , " r " ( ip < < 4 )
: " t " ) ;
}
2010-10-27 14:54:50 +09:00
static void mask_imask_irq ( struct irq_data * data )
2005-04-16 15:20:36 -07:00
{
2010-10-27 14:54:50 +09:00
unsigned int irq = data - > irq ;
2009-05-26 13:52:28 +09:00
clear_bit ( irq , imask_mask ) ;
2005-04-16 15:20:36 -07:00
if ( interrupt_priority < IMASK_PRIORITY - irq )
interrupt_priority = IMASK_PRIORITY - irq ;
set_interrupt_registers ( interrupt_priority ) ;
}
2010-10-27 14:54:50 +09:00
static void unmask_imask_irq ( struct irq_data * data )
2005-04-16 15:20:36 -07:00
{
2010-10-27 14:54:50 +09:00
unsigned int irq = data - > irq ;
2009-05-26 13:52:28 +09:00
set_bit ( irq , imask_mask ) ;
2009-05-22 01:16:17 +09:00
interrupt_priority = IMASK_PRIORITY -
find_first_zero_bit ( imask_mask , IMASK_PRIORITY ) ;
2005-04-16 15:20:36 -07:00
set_interrupt_registers ( interrupt_priority ) ;
}
2009-05-22 01:16:17 +09:00
static struct irq_chip imask_irq_chip = {
2009-11-17 22:50:45 +00:00
. name = " SR.IMASK " ,
2010-10-27 14:54:50 +09:00
. irq_mask = mask_imask_irq ,
. irq_unmask = unmask_imask_irq ,
. irq_mask_ack = mask_imask_irq ,
2009-05-22 01:16:17 +09:00
} ;
2005-04-16 15:20:36 -07:00
void make_imask_irq ( unsigned int irq )
{
2011-03-24 16:31:17 +01:00
irq_set_chip_and_handler_name ( irq , & imask_irq_chip , handle_level_irq ,
" level " ) ;
2005-04-16 15:20:36 -07:00
}