2007-10-02 12:15:23 +10:00
/*
* Interrupt controller driver for Xilinx Virtex FPGAs
*
* Copyright ( C ) 2007 Secret Lab Technologies Ltd .
*
* 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 .
*
*/
/*
* This is a driver for the interrupt controller typically found in
* Xilinx Virtex FPGA designs .
*
* The interrupt sense levels are hard coded into the FPGA design with
* typically a 1 : 1 relationship between irq lines and devices ( no shared
* irq lines ) . Therefore , this driver does not attempt to handle edge
* and level interrupts differently .
*/
# undef DEBUG
# include <linux/kernel.h>
# include <linux/irq.h>
# include <linux/of.h>
2013-09-26 07:40:04 -05:00
# include <linux/of_address.h>
2013-11-10 23:19:08 -06:00
# include <linux/of_irq.h>
2007-10-02 12:15:23 +10:00
# include <asm/io.h>
# include <asm/processor.h>
2009-06-06 10:15:03 -06:00
# include <asm/i8259.h>
2007-10-02 12:15:23 +10:00
# include <asm/irq.h>
2016-11-14 12:13:51 +00:00
# include <linux/irqchip.h>
2007-10-02 12:15:23 +10:00
2009-06-06 10:15:03 -06:00
# if defined(CONFIG_PPC_I8259)
/*
* Support code for cascading to 8259 interrupt controllers
*/
2015-09-14 10:42:37 +02:00
static void xilinx_i8259_cascade ( struct irq_desc * desc )
2009-06-06 10:15:03 -06:00
{
2011-03-25 16:45:20 +01:00
struct irq_chip * chip = irq_desc_get_chip ( desc ) ;
2009-06-06 10:15:03 -06:00
unsigned int cascade_irq = i8259_irq ( ) ;
2011-03-08 22:27:07 +00:00
2009-06-06 10:15:03 -06:00
if ( cascade_irq )
generic_handle_irq ( cascade_irq ) ;
/* Let xilinx_intc end the interrupt */
2011-03-08 22:27:07 +00:00
chip - > irq_unmask ( & desc - > irq_data ) ;
2009-06-06 10:15:03 -06:00
}
static void __init xilinx_i8259_setup_cascade ( void )
{
struct device_node * cascade_node ;
int cascade_irq ;
/* Initialize i8259 controller */
cascade_node = of_find_compatible_node ( NULL , NULL , " chrp,iic " ) ;
if ( ! cascade_node )
return ;
cascade_irq = irq_of_parse_and_map ( cascade_node , 0 ) ;
if ( ! cascade_irq ) {
pr_err ( " virtex_ml510: Failed to map cascade interrupt \n " ) ;
goto out ;
}
i8259_init ( cascade_node , 0 ) ;
2011-03-25 16:45:20 +01:00
irq_set_chained_handler ( cascade_irq , xilinx_i8259_cascade ) ;
2009-06-06 10:15:03 -06:00
2009-06-06 10:15:24 -06:00
/* Program irq 7 (usb/audio), 14/15 (ide) to level sensitive */
/* This looks like a dirty hack to me --gcl */
outb ( 0xc0 , 0x4d0 ) ;
outb ( 0xc0 , 0x4d1 ) ;
2009-06-06 10:15:03 -06:00
out :
of_node_put ( cascade_node ) ;
}
# else
static inline void xilinx_i8259_setup_cascade ( void ) { return ; }
# endif /* defined(CONFIG_PPC_I8259) */
/*
* Initialize master Xilinx interrupt controller
*/
2007-10-02 12:15:23 +10:00
void __init xilinx_intc_init_tree ( void )
{
2016-11-14 12:13:51 +00:00
irqchip_init ( ) ;
2009-06-06 10:15:03 -06:00
xilinx_i8259_setup_cascade ( ) ;
2007-10-02 12:15:23 +10:00
}