2009-08-06 16:12:43 +04:00
/*
* arch / arm / mach - dove / irq . c
*
* Dove IRQ handling .
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/irq.h>
# include <linux/gpio.h>
# include <linux/io.h>
# include <asm/mach/arch.h>
# include <plat/irq.h>
# include <asm/mach/irq.h>
# include <mach/pm.h>
# include <mach/bridge-regs.h>
# include "common.h"
static void gpio_irq_handler ( unsigned int irq , struct irq_desc * desc )
{
int irqoff ;
BUG_ON ( irq < IRQ_DOVE_GPIO_0_7 | | irq > IRQ_DOVE_HIGH_GPIO ) ;
irqoff = irq < = IRQ_DOVE_GPIO_16_23 ? irq - IRQ_DOVE_GPIO_0_7 :
3 + irq - IRQ_DOVE_GPIO_24_31 ;
orion_gpio_irq_handler ( irqoff < < 3 ) ;
if ( irq = = IRQ_DOVE_HIGH_GPIO ) {
orion_gpio_irq_handler ( 40 ) ;
orion_gpio_irq_handler ( 48 ) ;
orion_gpio_irq_handler ( 56 ) ;
}
}
2010-11-29 12:27:47 +03:00
static void pmu_irq_mask ( struct irq_data * d )
2009-08-06 16:12:43 +04:00
{
2010-11-29 12:27:47 +03:00
int pin = irq_to_pmu ( d - > irq ) ;
2009-08-06 16:12:43 +04:00
u32 u ;
u = readl ( PMU_INTERRUPT_MASK ) ;
u & = ~ ( 1 < < ( pin & 31 ) ) ;
writel ( u , PMU_INTERRUPT_MASK ) ;
}
2010-11-29 12:27:47 +03:00
static void pmu_irq_unmask ( struct irq_data * d )
2009-08-06 16:12:43 +04:00
{
2010-11-29 12:27:47 +03:00
int pin = irq_to_pmu ( d - > irq ) ;
2009-08-06 16:12:43 +04:00
u32 u ;
u = readl ( PMU_INTERRUPT_MASK ) ;
u | = 1 < < ( pin & 31 ) ;
writel ( u , PMU_INTERRUPT_MASK ) ;
}
2010-11-29 12:27:47 +03:00
static void pmu_irq_ack ( struct irq_data * d )
2009-08-06 16:12:43 +04:00
{
2010-11-29 12:27:47 +03:00
int pin = irq_to_pmu ( d - > irq ) ;
2009-08-06 16:12:43 +04:00
u32 u ;
u = ~ ( 1 < < ( pin & 31 ) ) ;
writel ( u , PMU_INTERRUPT_CAUSE ) ;
}
static struct irq_chip pmu_irq_chip = {
. name = " pmu_irq " ,
2010-11-29 12:27:47 +03:00
. irq_mask = pmu_irq_mask ,
. irq_unmask = pmu_irq_unmask ,
. irq_ack = pmu_irq_ack ,
2009-08-06 16:12:43 +04:00
} ;
static void pmu_irq_handler ( unsigned int irq , struct irq_desc * desc )
{
unsigned long cause = readl ( PMU_INTERRUPT_CAUSE ) ;
cause & = readl ( PMU_INTERRUPT_MASK ) ;
if ( cause = = 0 ) {
do_bad_IRQ ( irq , desc ) ;
return ;
}
for ( irq = 0 ; irq < NR_PMU_IRQS ; irq + + ) {
if ( ! ( cause & ( 1 < < irq ) ) )
continue ;
irq = pmu_to_irq ( irq ) ;
2011-03-24 14:33:40 +03:00
generic_handle_irq ( irq ) ;
2009-08-06 16:12:43 +04:00
}
}
void __init dove_init_irq ( void )
{
int i ;
orion_irq_init ( 0 , ( void __iomem * ) ( IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF ) ) ;
orion_irq_init ( 32 , ( void __iomem * ) ( IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF ) ) ;
/*
2010-12-14 14:54:03 +03:00
* Initialize gpiolib for GPIOs 0 - 71.
2009-08-06 16:12:43 +04:00
*/
2010-12-14 14:54:03 +03:00
orion_gpio_init ( 0 , 32 , DOVE_GPIO_LO_VIRT_BASE , 0 ,
IRQ_DOVE_GPIO_START ) ;
2011-03-24 15:25:22 +03:00
irq_set_chained_handler ( IRQ_DOVE_GPIO_0_7 , gpio_irq_handler ) ;
irq_set_chained_handler ( IRQ_DOVE_GPIO_8_15 , gpio_irq_handler ) ;
irq_set_chained_handler ( IRQ_DOVE_GPIO_16_23 , gpio_irq_handler ) ;
irq_set_chained_handler ( IRQ_DOVE_GPIO_24_31 , gpio_irq_handler ) ;
2010-12-14 14:54:03 +03:00
orion_gpio_init ( 32 , 32 , DOVE_GPIO_HI_VIRT_BASE , 0 ,
IRQ_DOVE_GPIO_START + 32 ) ;
2011-03-24 15:25:22 +03:00
irq_set_chained_handler ( IRQ_DOVE_HIGH_GPIO , gpio_irq_handler ) ;
2010-12-14 14:54:03 +03:00
orion_gpio_init ( 64 , 8 , DOVE_GPIO2_VIRT_BASE , 0 ,
IRQ_DOVE_GPIO_START + 64 ) ;
2009-08-06 16:12:43 +04:00
/*
* Mask and clear PMU interrupts
*/
writel ( 0 , PMU_INTERRUPT_MASK ) ;
writel ( 0 , PMU_INTERRUPT_CAUSE ) ;
for ( i = IRQ_DOVE_PMU_START ; i < NR_IRQS ; i + + ) {
2011-03-24 15:35:09 +03:00
irq_set_chip_and_handler ( i , & pmu_irq_chip , handle_level_irq ) ;
2011-03-24 14:33:40 +03:00
irq_set_status_flags ( i , IRQ_LEVEL ) ;
2009-08-06 16:12:43 +04:00
set_irq_flags ( i , IRQF_VALID ) ;
}
2011-03-24 15:25:22 +03:00
irq_set_chained_handler ( IRQ_DOVE_PMU , pmu_irq_handler ) ;
2009-08-06 16:12:43 +04:00
}