2018-08-04 10:23:16 +02:00
// SPDX-License-Identifier: GPL-2.0
2017-07-10 18:00:26 -07:00
/*
* Copyright ( C ) 2012 Regents of the University of California
* Copyright ( C ) 2017 SiFive
2018-08-04 10:23:16 +02:00
* Copyright ( C ) 2018 Christoph Hellwig
2017-07-10 18:00:26 -07:00
*/
# include <linux/interrupt.h>
# include <linux/irqchip.h>
2023-03-28 09:22:18 +05:30
# include <linux/irqdomain.h>
# include <linux/module.h>
2018-10-02 12:15:07 -07:00
# include <linux/seq_file.h>
2023-03-28 09:22:19 +05:30
# include <asm/sbi.h>
2023-06-13 21:30:17 -04:00
# include <asm/smp.h>
# include <asm/softirq_stack.h>
# include <asm/stacktrace.h>
2017-07-10 18:00:26 -07:00
2023-03-28 09:22:18 +05:30
static struct fwnode_handle * ( * __get_intc_node ) ( void ) ;
void riscv_set_intc_hwnode_fn ( struct fwnode_handle * ( * fn ) ( void ) )
{
__get_intc_node = fn ;
}
struct fwnode_handle * riscv_get_intc_hwnode ( void )
{
if ( __get_intc_node )
return __get_intc_node ( ) ;
return NULL ;
}
EXPORT_SYMBOL_GPL ( riscv_get_intc_hwnode ) ;
2023-06-13 21:30:16 -04:00
# ifdef CONFIG_IRQ_STACKS
# include <asm/irq_stack.h>
DEFINE_PER_CPU ( ulong * , irq_stack_ptr ) ;
# ifdef CONFIG_VMAP_STACK
static void init_irq_stacks ( void )
{
int cpu ;
ulong * p ;
for_each_possible_cpu ( cpu ) {
p = arch_alloc_vmap_stack ( IRQ_STACK_SIZE , cpu_to_node ( cpu ) ) ;
per_cpu ( irq_stack_ptr , cpu ) = p ;
}
}
# else
/* irq stack only needs to be 16 byte aligned - not IRQ_STACK_SIZE aligned. */
DEFINE_PER_CPU_ALIGNED ( ulong [ IRQ_STACK_SIZE / sizeof ( ulong ) ] , irq_stack ) ;
static void init_irq_stacks ( void )
{
int cpu ;
for_each_possible_cpu ( cpu )
per_cpu ( irq_stack_ptr , cpu ) = per_cpu ( irq_stack , cpu ) ;
}
# endif /* CONFIG_VMAP_STACK */
2023-06-13 21:30:17 -04:00
# ifdef CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK
void do_softirq_own_stack ( void )
{
# ifdef CONFIG_IRQ_STACKS
if ( on_thread_stack ( ) ) {
ulong * sp = per_cpu ( irq_stack_ptr , smp_processor_id ( ) )
+ IRQ_STACK_SIZE / sizeof ( ulong ) ;
__asm__ __volatile (
" addi sp, sp, - " RISCV_SZPTR " \n "
REG_S " ra, (sp) \n "
" addi sp, sp, - " RISCV_SZPTR " \n "
REG_S " s0, (sp) \n "
" addi s0, sp, 2* " RISCV_SZPTR " \n "
" move sp, %[sp] \n "
" call __do_softirq \n "
" addi sp, s0, -2* " RISCV_SZPTR " \n "
REG_L " s0, (sp) \n "
" addi sp, sp, " RISCV_SZPTR " \n "
REG_L " ra, (sp) \n "
" addi sp, sp, " RISCV_SZPTR " \n "
:
: [ sp ] " r " ( sp )
: " a0 " , " a1 " , " a2 " , " a3 " , " a4 " , " a5 " , " a6 " , " a7 " ,
" t0 " , " t1 " , " t2 " , " t3 " , " t4 " , " t5 " , " t6 " ,
2023-07-15 20:15:06 -04:00
# ifndef CONFIG_FRAME_POINTER
" s0 " ,
# endif
2023-06-13 21:30:17 -04:00
" memory " ) ;
} else
# endif
__do_softirq ( ) ;
}
# endif /* CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK */
2023-06-13 21:30:16 -04:00
# else
static void init_irq_stacks ( void ) { }
# endif /* CONFIG_IRQ_STACKS */
2018-10-02 12:15:07 -07:00
int arch_show_interrupts ( struct seq_file * p , int prec )
{
show_ipi_stats ( p , prec ) ;
return 0 ;
}
2017-07-10 18:00:26 -07:00
void __init init_IRQ ( void )
{
2023-06-13 21:30:16 -04:00
init_irq_stacks ( ) ;
2017-07-10 18:00:26 -07:00
irqchip_init ( ) ;
2020-06-01 14:45:40 +05:30
if ( ! handle_arch_irq )
panic ( " No interrupt controller found. " ) ;
2023-03-28 09:22:19 +05:30
sbi_ipi_init ( ) ;
2017-07-10 18:00:26 -07:00
}