2009-08-07 19:59:04 +01:00
/*
*
* Copyright ( C ) 1999 ARM Limited
*
* 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 , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/init.h>
# include <linux/stddef.h>
# include <linux/list.h>
# include <linux/timer.h>
# include <linux/io.h>
# include <mach/hardware.h>
# include <asm/irq.h>
# include <asm/mach/irq.h>
# include <mach/csp/intcHw_reg.h>
# include <mach/csp/mm_io.h>
2010-11-29 10:26:37 +01:00
static void bcmring_mask_irq0 ( struct irq_data * d )
2009-08-07 19:59:04 +01:00
{
2010-11-29 10:26:37 +01:00
writel ( 1 < < ( d - > irq - IRQ_INTC0_START ) ,
2009-08-07 19:59:04 +01:00
MM_IO_BASE_INTC0 + INTCHW_INTENCLEAR ) ;
}
2010-11-29 10:26:37 +01:00
static void bcmring_unmask_irq0 ( struct irq_data * d )
2009-08-07 19:59:04 +01:00
{
2010-11-29 10:26:37 +01:00
writel ( 1 < < ( d - > irq - IRQ_INTC0_START ) ,
2009-08-07 19:59:04 +01:00
MM_IO_BASE_INTC0 + INTCHW_INTENABLE ) ;
}
2010-11-29 10:26:37 +01:00
static void bcmring_mask_irq1 ( struct irq_data * d )
2009-08-07 19:59:04 +01:00
{
2010-11-29 10:26:37 +01:00
writel ( 1 < < ( d - > irq - IRQ_INTC1_START ) ,
2009-08-07 19:59:04 +01:00
MM_IO_BASE_INTC1 + INTCHW_INTENCLEAR ) ;
}
2010-11-29 10:26:37 +01:00
static void bcmring_unmask_irq1 ( struct irq_data * d )
2009-08-07 19:59:04 +01:00
{
2010-11-29 10:26:37 +01:00
writel ( 1 < < ( d - > irq - IRQ_INTC1_START ) ,
2009-08-07 19:59:04 +01:00
MM_IO_BASE_INTC1 + INTCHW_INTENABLE ) ;
}
2010-11-29 10:26:37 +01:00
static void bcmring_mask_irq2 ( struct irq_data * d )
2009-08-07 19:59:04 +01:00
{
2010-11-29 10:26:37 +01:00
writel ( 1 < < ( d - > irq - IRQ_SINTC_START ) ,
2009-08-07 19:59:04 +01:00
MM_IO_BASE_SINTC + INTCHW_INTENCLEAR ) ;
}
2010-11-29 10:26:37 +01:00
static void bcmring_unmask_irq2 ( struct irq_data * d )
2009-08-07 19:59:04 +01:00
{
2010-11-29 10:26:37 +01:00
writel ( 1 < < ( d - > irq - IRQ_SINTC_START ) ,
2009-08-07 19:59:04 +01:00
MM_IO_BASE_SINTC + INTCHW_INTENABLE ) ;
}
static struct irq_chip bcmring_irq0_chip = {
2010-09-23 18:40:07 +02:00
. name = " ARM-INTC0 " ,
2010-11-29 10:26:37 +01:00
. irq_ack = bcmring_mask_irq0 ,
. irq_mask = bcmring_mask_irq0 , /* mask a specific interrupt, blocking its delivery. */
. irq_unmask = bcmring_unmask_irq0 , /* unmaks an interrupt */
2009-08-07 19:59:04 +01:00
} ;
static struct irq_chip bcmring_irq1_chip = {
2010-09-23 18:40:07 +02:00
. name = " ARM-INTC1 " ,
2010-11-29 10:26:37 +01:00
. irq_ack = bcmring_mask_irq1 ,
. irq_mask = bcmring_mask_irq1 ,
. irq_unmask = bcmring_unmask_irq1 ,
2009-08-07 19:59:04 +01:00
} ;
static struct irq_chip bcmring_irq2_chip = {
2010-09-23 18:40:07 +02:00
. name = " ARM-SINTC " ,
2010-11-29 10:26:37 +01:00
. irq_ack = bcmring_mask_irq2 ,
. irq_mask = bcmring_mask_irq2 ,
. irq_unmask = bcmring_unmask_irq2 ,
2009-08-07 19:59:04 +01:00
} ;
static void vic_init ( void __iomem * base , struct irq_chip * chip ,
unsigned int irq_start , unsigned int vic_sources )
{
unsigned int i ;
for ( i = 0 ; i < 32 ; i + + ) {
unsigned int irq = irq_start + i ;
2011-03-24 13:25:22 +01:00
irq_set_chip ( irq , chip ) ;
irq_set_chip_data ( irq , base ) ;
2009-08-07 19:59:04 +01:00
if ( vic_sources & ( 1 < < i ) ) {
2011-03-24 13:25:22 +01:00
irq_set_handler ( irq , handle_level_irq ) ;
2009-08-07 19:59:04 +01:00
set_irq_flags ( irq , IRQF_VALID | IRQF_PROBE ) ;
}
}
writel ( 0 , base + INTCHW_INTSELECT ) ;
writel ( 0 , base + INTCHW_INTENABLE ) ;
writel ( ~ 0 , base + INTCHW_INTENCLEAR ) ;
writel ( 0 , base + INTCHW_IRQSTATUS ) ;
writel ( ~ 0 , base + INTCHW_SOFTINTCLEAR ) ;
}
void __init bcmring_init_irq ( void )
{
vic_init ( ( void __iomem * ) MM_IO_BASE_INTC0 , & bcmring_irq0_chip ,
IRQ_INTC0_START , IRQ_INTC0_VALID_MASK ) ;
vic_init ( ( void __iomem * ) MM_IO_BASE_INTC1 , & bcmring_irq1_chip ,
IRQ_INTC1_START , IRQ_INTC1_VALID_MASK ) ;
vic_init ( ( void __iomem * ) MM_IO_BASE_SINTC , & bcmring_irq2_chip ,
IRQ_SINTC_START , IRQ_SINTC_VALID_MASK ) ;
/* special cases */
if ( INTCHW_INTC1_GPIO0 & IRQ_INTC1_VALID_MASK ) {
2011-03-24 13:25:22 +01:00
irq_set_handler ( IRQ_GPIO0 , handle_simple_irq ) ;
2009-08-07 19:59:04 +01:00
}
if ( INTCHW_INTC1_GPIO1 & IRQ_INTC1_VALID_MASK ) {
2011-03-24 13:25:22 +01:00
irq_set_handler ( IRQ_GPIO1 , handle_simple_irq ) ;
2009-08-07 19:59:04 +01:00
}
}