2006-06-19 18:27:53 +04:00
/*
* arch / arm / mach - netx / generic . c
*
* Copyright ( C ) 2005 Sascha Hauer < s . hauer @ pengutronix . de > , Pengutronix
*
* 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 .
*
* 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/device.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/platform_device.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2006-06-19 18:27:53 +04:00
# include <asm/mach/map.h>
# include <asm/hardware/vic.h>
2008-08-05 19:14:15 +04:00
# include <mach/netx-regs.h>
2006-06-19 18:27:53 +04:00
# include <asm/mach/irq.h>
static struct map_desc netx_io_desc [ ] __initdata = {
{
. virtual = NETX_IO_VIRT ,
. pfn = __phys_to_pfn ( NETX_IO_PHYS ) ,
. length = NETX_IO_SIZE ,
. type = MT_DEVICE
}
} ;
void __init netx_map_io ( void )
{
iotable_init ( netx_io_desc , ARRAY_SIZE ( netx_io_desc ) ) ;
}
static struct resource netx_rtc_resources [ ] = {
[ 0 ] = {
. start = 0x00101200 ,
. end = 0x00101220 ,
. flags = IORESOURCE_MEM ,
} ,
} ;
static struct platform_device netx_rtc_device = {
. name = " netx-rtc " ,
. id = 0 ,
. num_resources = ARRAY_SIZE ( netx_rtc_resources ) ,
. resource = netx_rtc_resources ,
} ;
static struct platform_device * devices [ ] __initdata = {
& netx_rtc_device ,
} ;
#if 0
# define DEBUG_IRQ(fmt...) printk(fmt)
# else
# define DEBUG_IRQ(fmt...) while (0) {}
# endif
static void
2006-11-23 14:41:32 +03:00
netx_hif_demux_handler ( unsigned int irq_unused , struct irq_desc * desc )
2006-06-19 18:27:53 +04:00
{
unsigned int irq = NETX_IRQ_HIF_CHAINED ( 0 ) ;
unsigned int stat ;
stat = ( ( readl ( NETX_DPMAS_INT_EN ) &
readl ( NETX_DPMAS_INT_STAT ) ) > > 24 ) & 0x1f ;
while ( stat ) {
if ( stat & 1 ) {
DEBUG_IRQ ( " handling irq %d \n " , irq ) ;
2008-10-09 16:36:24 +04:00
generic_handle_irq ( irq ) ;
2006-06-19 18:27:53 +04:00
}
irq + + ;
stat > > = 1 ;
}
}
static int
2010-11-29 12:38:10 +03:00
netx_hif_irq_type ( struct irq_data * d , unsigned int type )
2006-06-19 18:27:53 +04:00
{
unsigned int val , irq ;
val = readl ( NETX_DPMAS_IF_CONF1 ) ;
2010-11-29 12:38:10 +03:00
irq = d - > irq - NETX_IRQ_HIF_CHAINED ( 0 ) ;
2006-06-19 18:27:53 +04:00
2008-07-27 07:23:31 +04:00
if ( type & IRQ_TYPE_EDGE_RISING ) {
2006-06-19 18:27:53 +04:00
DEBUG_IRQ ( " rising edges \n " ) ;
val | = ( 1 < < 26 ) < < irq ;
}
2008-07-27 07:23:31 +04:00
if ( type & IRQ_TYPE_EDGE_FALLING ) {
2006-06-19 18:27:53 +04:00
DEBUG_IRQ ( " falling edges \n " ) ;
val & = ~ ( ( 1 < < 26 ) < < irq ) ;
}
2008-07-27 07:23:31 +04:00
if ( type & IRQ_TYPE_LEVEL_LOW ) {
2006-06-19 18:27:53 +04:00
DEBUG_IRQ ( " low level \n " ) ;
val & = ~ ( ( 1 < < 26 ) < < irq ) ;
}
2008-07-27 07:23:31 +04:00
if ( type & IRQ_TYPE_LEVEL_HIGH ) {
2006-06-19 18:27:53 +04:00
DEBUG_IRQ ( " high level \n " ) ;
val | = ( 1 < < 26 ) < < irq ;
}
writel ( val , NETX_DPMAS_IF_CONF1 ) ;
return 0 ;
}
static void
2010-11-29 12:38:10 +03:00
netx_hif_ack_irq ( struct irq_data * d )
2006-06-19 18:27:53 +04:00
{
unsigned int val , irq ;
2010-11-29 12:38:10 +03:00
irq = d - > irq - NETX_IRQ_HIF_CHAINED ( 0 ) ;
2006-06-19 18:27:53 +04:00
writel ( ( 1 < < 24 ) < < irq , NETX_DPMAS_INT_STAT ) ;
val = readl ( NETX_DPMAS_INT_EN ) ;
val & = ~ ( ( 1 < < 24 ) < < irq ) ;
writel ( val , NETX_DPMAS_INT_EN ) ;
2010-11-29 12:38:10 +03:00
DEBUG_IRQ ( " %s: irq %d \n " , __func__ , d - > irq ) ;
2006-06-19 18:27:53 +04:00
}
static void
2010-11-29 12:38:10 +03:00
netx_hif_mask_irq ( struct irq_data * d )
2006-06-19 18:27:53 +04:00
{
unsigned int val , irq ;
2010-11-29 12:38:10 +03:00
irq = d - > irq - NETX_IRQ_HIF_CHAINED ( 0 ) ;
2006-06-19 18:27:53 +04:00
val = readl ( NETX_DPMAS_INT_EN ) ;
val & = ~ ( ( 1 < < 24 ) < < irq ) ;
writel ( val , NETX_DPMAS_INT_EN ) ;
2010-11-29 12:38:10 +03:00
DEBUG_IRQ ( " %s: irq %d \n " , __func__ , d - > irq ) ;
2006-06-19 18:27:53 +04:00
}
static void
2010-11-29 12:38:10 +03:00
netx_hif_unmask_irq ( struct irq_data * d )
2006-06-19 18:27:53 +04:00
{
unsigned int val , irq ;
2010-11-29 12:38:10 +03:00
irq = d - > irq - NETX_IRQ_HIF_CHAINED ( 0 ) ;
2006-06-19 18:27:53 +04:00
val = readl ( NETX_DPMAS_INT_EN ) ;
val | = ( 1 < < 24 ) < < irq ;
writel ( val , NETX_DPMAS_INT_EN ) ;
2010-11-29 12:38:10 +03:00
DEBUG_IRQ ( " %s: irq %d \n " , __func__ , d - > irq ) ;
2006-06-19 18:27:53 +04:00
}
2006-11-23 14:41:32 +03:00
static struct irq_chip netx_hif_chip = {
2010-11-29 12:38:10 +03:00
. irq_ack = netx_hif_ack_irq ,
. irq_mask = netx_hif_mask_irq ,
. irq_unmask = netx_hif_unmask_irq ,
. irq_set_type = netx_hif_irq_type ,
2006-06-19 18:27:53 +04:00
} ;
void __init netx_init_irq ( void )
{
int irq ;
2009-03-24 18:30:07 +03:00
vic_init ( __io ( io_p2v ( NETX_PA_VIC ) ) , 0 , ~ 0 , 0 ) ;
2006-06-19 18:27:53 +04:00
for ( irq = NETX_IRQ_HIF_CHAINED ( 0 ) ; irq < = NETX_IRQ_HIF_LAST ; irq + + ) {
2011-03-24 15:35:09 +03:00
irq_set_chip_and_handler ( irq , & netx_hif_chip ,
handle_level_irq ) ;
2006-06-19 18:27:53 +04:00
set_irq_flags ( irq , IRQF_VALID ) ;
}
writel ( NETX_DPMAS_INT_EN_GLB_EN , NETX_DPMAS_INT_EN ) ;
2011-03-24 15:25:22 +03:00
irq_set_chained_handler ( NETX_IRQ_HIF , netx_hif_demux_handler ) ;
2006-06-19 18:27:53 +04:00
}
static int __init netx_init ( void )
{
return platform_add_devices ( devices , ARRAY_SIZE ( devices ) ) ;
}
subsys_initcall ( netx_init ) ;