2013-01-18 15:12:16 +05:30
/*
* Copyright ( C ) 2011 - 12 Synopsys , Inc . ( www . synopsys . com )
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
*/
# include <linux/interrupt.h>
2013-04-11 14:47:36 +05:30
# include <linux/irqchip.h>
2013-01-18 15:12:26 +05:30
# include <asm/mach_desc.h>
2015-10-14 14:38:02 +05:30
# include <asm/smp.h>
2013-01-18 15:12:18 +05:30
/*
* Late Interrupt system init called from start_kernel for Boot CPU only
*
* Since slab must already be initialized , platforms can start doing any
* needed request_irq ( ) s
*/
void __init init_IRQ ( void )
{
2015-10-13 08:48:54 +05:30
/*
* process the entire interrupt tree in one go
* Any external intc will be setup provided DT chains them
* properly
*/
2013-04-11 14:47:36 +05:30
irqchip_init ( ) ;
2013-01-18 15:12:23 +05:30
# ifdef CONFIG_SMP
2015-10-14 14:38:02 +05:30
/* a SMP H/w block could do IPI IRQ request here */
2015-12-16 03:10:27 +02:00
if ( plat_smp_ops . init_per_cpu )
plat_smp_ops . init_per_cpu ( smp_processor_id ( ) ) ;
2015-10-14 14:38:02 +05:30
2015-10-13 15:26:00 +05:30
if ( machine_desc - > init_cpu_smp )
machine_desc - > init_cpu_smp ( smp_processor_id ( ) ) ;
2013-01-18 15:12:23 +05:30
# endif
2013-01-18 15:12:18 +05:30
}
/*
* " C " Entry point for any ARC ISR , called from low level vector handler
* @ irq is the vector number read from ICAUSE reg of on - chip intc
*/
void arch_do_IRQ ( unsigned int irq , struct pt_regs * regs )
{
struct pt_regs * old_regs = set_irq_regs ( regs ) ;
irq_enter ( ) ;
generic_handle_irq ( irq ) ;
irq_exit ( ) ;
set_irq_regs ( old_regs ) ;
}
2015-12-11 19:31:23 +05:30
/*
* API called for requesting percpu interrupts - called by each CPU
* - For boot CPU , actually request the IRQ with genirq core + enables
* - For subsequent callers only enable called locally
*
* Relies on being called by boot cpu first ( i . e . request called ahead ) of
* any enable as expected by genirq . Hence Suitable only for TIMER , IPI
* which are guaranteed to be setup on boot core first .
* Late probed peripherals such as perf can ' t use this as there no guarantee
* of being called on boot CPU first .
*/
2014-05-07 15:25:10 +05:30
void arc_request_percpu_irq ( int irq , int cpu ,
irqreturn_t ( * isr ) ( int irq , void * dev ) ,
const char * irq_nm ,
void * percpu_dev )
{
/* Boot cpu calls request, all call enable */
if ( ! cpu ) {
int rc ;
2015-12-11 16:16:11 +05:30
# ifdef CONFIG_ISA_ARCOMPACT
2014-05-07 15:25:10 +05:30
/*
2015-12-11 16:16:11 +05:30
* A subsequent request_percpu_irq ( ) fails if percpu_devid is
* not set . That in turns sets NOAUTOEN , meaning each core needs
* to call enable_percpu_irq ( )
*
* For ARCv2 , this is done in irq map function since we know
* which irqs are strictly per cpu
2014-05-07 15:25:10 +05:30
*/
irq_set_percpu_devid ( irq ) ;
2015-12-11 16:16:11 +05:30
# endif
2014-05-07 15:25:10 +05:30
rc = request_percpu_irq ( irq , isr , irq_nm , percpu_dev ) ;
if ( rc )
panic ( " Percpu IRQ request failed for %d \n " , irq ) ;
}
enable_percpu_irq ( irq , 0 ) ;
}