2006-12-07 02:59:39 +01:00
/*
* iop13xx IRQ handling / support functions
* Copyright ( c ) 2005 - 2006 , Intel Corporation .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope 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 , write to the Free Software Foundation , Inc . , 59 Temple
* Place - Suite 330 , Boston , MA 02111 - 1307 USA .
*
*/
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/list.h>
# include <linux/sysctl.h>
# include <asm/uaccess.h>
# include <asm/mach/irq.h>
# include <asm/irq.h>
2008-08-05 16:14:15 +01:00
# include <mach/hardware.h>
# include <mach/irqs.h>
2015-01-30 10:45:33 +01:00
# include "msi.h"
2006-12-07 02:59:39 +01:00
/* INTCTL0 CP6 R0 Page 4
*/
2007-05-15 01:03:36 +01:00
static u32 read_intctl_0 ( void )
2006-12-07 02:59:39 +01:00
{
u32 val ;
asm volatile ( " mrc p6, 0, %0, c0, c4, 0 " : " =r " ( val ) ) ;
return val ;
}
2007-05-15 01:03:36 +01:00
static void write_intctl_0 ( u32 val )
2006-12-07 02:59:39 +01:00
{
asm volatile ( " mcr p6, 0, %0, c0, c4, 0 " : : " r " ( val ) ) ;
}
/* INTCTL1 CP6 R1 Page 4
*/
2007-05-15 01:03:36 +01:00
static u32 read_intctl_1 ( void )
2006-12-07 02:59:39 +01:00
{
u32 val ;
asm volatile ( " mrc p6, 0, %0, c1, c4, 0 " : " =r " ( val ) ) ;
return val ;
}
2007-05-15 01:03:36 +01:00
static void write_intctl_1 ( u32 val )
2006-12-07 02:59:39 +01:00
{
asm volatile ( " mcr p6, 0, %0, c1, c4, 0 " : : " r " ( val ) ) ;
}
/* INTCTL2 CP6 R2 Page 4
*/
2007-05-15 01:03:36 +01:00
static u32 read_intctl_2 ( void )
2006-12-07 02:59:39 +01:00
{
u32 val ;
asm volatile ( " mrc p6, 0, %0, c2, c4, 0 " : " =r " ( val ) ) ;
return val ;
}
2007-05-15 01:03:36 +01:00
static void write_intctl_2 ( u32 val )
2006-12-07 02:59:39 +01:00
{
asm volatile ( " mcr p6, 0, %0, c2, c4, 0 " : : " r " ( val ) ) ;
}
/* INTCTL3 CP6 R3 Page 4
*/
2007-05-15 01:03:36 +01:00
static u32 read_intctl_3 ( void )
2006-12-07 02:59:39 +01:00
{
u32 val ;
asm volatile ( " mrc p6, 0, %0, c3, c4, 0 " : " =r " ( val ) ) ;
return val ;
}
2007-05-15 01:03:36 +01:00
static void write_intctl_3 ( u32 val )
2006-12-07 02:59:39 +01:00
{
asm volatile ( " mcr p6, 0, %0, c3, c4, 0 " : : " r " ( val ) ) ;
}
/* INTSTR0 CP6 R0 Page 5
*/
2007-05-15 01:03:36 +01:00
static void write_intstr_0 ( u32 val )
2006-12-07 02:59:39 +01:00
{
asm volatile ( " mcr p6, 0, %0, c0, c5, 0 " : : " r " ( val ) ) ;
}
/* INTSTR1 CP6 R1 Page 5
*/
static void write_intstr_1 ( u32 val )
{
asm volatile ( " mcr p6, 0, %0, c1, c5, 0 " : : " r " ( val ) ) ;
}
/* INTSTR2 CP6 R2 Page 5
*/
static void write_intstr_2 ( u32 val )
{
asm volatile ( " mcr p6, 0, %0, c2, c5, 0 " : : " r " ( val ) ) ;
}
/* INTSTR3 CP6 R3 Page 5
*/
static void write_intstr_3 ( u32 val )
{
asm volatile ( " mcr p6, 0, %0, c3, c5, 0 " : : " r " ( val ) ) ;
}
/* INTBASE CP6 R0 Page 2
*/
static void write_intbase ( u32 val )
{
asm volatile ( " mcr p6, 0, %0, c0, c2, 0 " : : " r " ( val ) ) ;
}
/* INTSIZE CP6 R2 Page 2
*/
static void write_intsize ( u32 val )
{
asm volatile ( " mcr p6, 0, %0, c2, c2, 0 " : : " r " ( val ) ) ;
}
/* 0 = Interrupt Masked and 1 = Interrupt not masked */
static void
2010-11-29 10:32:01 +01:00
iop13xx_irq_mask0 ( struct irq_data * d )
2006-12-07 02:59:39 +01:00
{
2010-11-29 10:32:01 +01:00
write_intctl_0 ( read_intctl_0 ( ) & ~ ( 1 < < ( d - > irq - 0 ) ) ) ;
2006-12-07 02:59:39 +01:00
}
static void
2010-11-29 10:32:01 +01:00
iop13xx_irq_mask1 ( struct irq_data * d )
2006-12-07 02:59:39 +01:00
{
2010-11-29 10:32:01 +01:00
write_intctl_1 ( read_intctl_1 ( ) & ~ ( 1 < < ( d - > irq - 32 ) ) ) ;
2006-12-07 02:59:39 +01:00
}
static void
2010-11-29 10:32:01 +01:00
iop13xx_irq_mask2 ( struct irq_data * d )
2006-12-07 02:59:39 +01:00
{
2010-11-29 10:32:01 +01:00
write_intctl_2 ( read_intctl_2 ( ) & ~ ( 1 < < ( d - > irq - 64 ) ) ) ;
2006-12-07 02:59:39 +01:00
}
static void
2010-11-29 10:32:01 +01:00
iop13xx_irq_mask3 ( struct irq_data * d )
2006-12-07 02:59:39 +01:00
{
2010-11-29 10:32:01 +01:00
write_intctl_3 ( read_intctl_3 ( ) & ~ ( 1 < < ( d - > irq - 96 ) ) ) ;
2006-12-07 02:59:39 +01:00
}
static void
2010-11-29 10:32:01 +01:00
iop13xx_irq_unmask0 ( struct irq_data * d )
2006-12-07 02:59:39 +01:00
{
2010-11-29 10:32:01 +01:00
write_intctl_0 ( read_intctl_0 ( ) | ( 1 < < ( d - > irq - 0 ) ) ) ;
2006-12-07 02:59:39 +01:00
}
static void
2010-11-29 10:32:01 +01:00
iop13xx_irq_unmask1 ( struct irq_data * d )
2006-12-07 02:59:39 +01:00
{
2010-11-29 10:32:01 +01:00
write_intctl_1 ( read_intctl_1 ( ) | ( 1 < < ( d - > irq - 32 ) ) ) ;
2006-12-07 02:59:39 +01:00
}
static void
2010-11-29 10:32:01 +01:00
iop13xx_irq_unmask2 ( struct irq_data * d )
2006-12-07 02:59:39 +01:00
{
2010-11-29 10:32:01 +01:00
write_intctl_2 ( read_intctl_2 ( ) | ( 1 < < ( d - > irq - 64 ) ) ) ;
2006-12-07 02:59:39 +01:00
}
static void
2010-11-29 10:32:01 +01:00
iop13xx_irq_unmask3 ( struct irq_data * d )
2006-12-07 02:59:39 +01:00
{
2010-11-29 10:32:01 +01:00
write_intctl_3 ( read_intctl_3 ( ) | ( 1 < < ( d - > irq - 96 ) ) ) ;
2006-12-07 02:59:39 +01:00
}
2006-12-14 23:31:20 +01:00
static struct irq_chip iop13xx_irqchip1 = {
2010-11-29 10:32:01 +01:00
. name = " IOP13xx-1 " ,
. irq_ack = iop13xx_irq_mask0 ,
. irq_mask = iop13xx_irq_mask0 ,
. irq_unmask = iop13xx_irq_unmask0 ,
2006-12-07 02:59:39 +01:00
} ;
2006-12-14 23:31:20 +01:00
static struct irq_chip iop13xx_irqchip2 = {
2010-11-29 10:32:01 +01:00
. name = " IOP13xx-2 " ,
. irq_ack = iop13xx_irq_mask1 ,
. irq_mask = iop13xx_irq_mask1 ,
. irq_unmask = iop13xx_irq_unmask1 ,
2006-12-07 02:59:39 +01:00
} ;
2006-12-14 23:31:20 +01:00
static struct irq_chip iop13xx_irqchip3 = {
2010-11-29 10:32:01 +01:00
. name = " IOP13xx-3 " ,
. irq_ack = iop13xx_irq_mask2 ,
. irq_mask = iop13xx_irq_mask2 ,
. irq_unmask = iop13xx_irq_unmask2 ,
2006-12-07 02:59:39 +01:00
} ;
2006-12-14 23:31:20 +01:00
static struct irq_chip iop13xx_irqchip4 = {
2010-11-29 10:32:01 +01:00
. name = " IOP13xx-4 " ,
. irq_ack = iop13xx_irq_mask3 ,
. irq_mask = iop13xx_irq_mask3 ,
. irq_unmask = iop13xx_irq_unmask3 ,
2006-12-07 02:59:39 +01:00
} ;
2007-02-13 17:12:04 +01:00
extern void iop_init_cp6_handler ( void ) ;
2006-12-07 02:59:39 +01:00
void __init iop13xx_init_irq ( void )
{
unsigned int i ;
2007-02-13 17:12:04 +01:00
iop_init_cp6_handler ( ) ;
2006-12-07 02:59:39 +01:00
/* disable all interrupts */
write_intctl_0 ( 0 ) ;
write_intctl_1 ( 0 ) ;
write_intctl_2 ( 0 ) ;
write_intctl_3 ( 0 ) ;
/* treat all as IRQ */
write_intstr_0 ( 0 ) ;
write_intstr_1 ( 0 ) ;
write_intstr_2 ( 0 ) ;
write_intstr_3 ( 0 ) ;
/* initialize the interrupt vector generator */
write_intbase ( INTBASE ) ;
write_intsize ( INTSIZE_4 ) ;
2007-05-10 22:33:02 -07:00
for ( i = 0 ; i < = IRQ_IOP13XX_HPI ; i + + ) {
2006-12-07 02:59:39 +01:00
if ( i < 32 )
2011-03-24 13:25:22 +01:00
irq_set_chip ( i , & iop13xx_irqchip1 ) ;
2006-12-14 23:31:20 +01:00
else if ( i < 64 )
2011-03-24 13:25:22 +01:00
irq_set_chip ( i , & iop13xx_irqchip2 ) ;
2006-12-14 23:31:20 +01:00
else if ( i < 96 )
2011-03-24 13:25:22 +01:00
irq_set_chip ( i , & iop13xx_irqchip3 ) ;
2006-12-14 23:31:20 +01:00
else
2011-03-24 13:25:22 +01:00
irq_set_chip ( i , & iop13xx_irqchip4 ) ;
2006-12-07 02:59:39 +01:00
2011-03-24 13:25:22 +01:00
irq_set_handler ( i , handle_level_irq ) ;
2015-07-27 15:55:13 -05:00
irq_clear_status_flags ( i , IRQ_NOREQUEST | IRQ_NOPROBE ) ;
2006-12-07 02:59:39 +01:00
}
2007-05-10 22:33:02 -07:00
iop13xx_msi_init ( ) ;
2006-12-07 02:59:39 +01:00
}