2005-04-16 15:20:36 -07:00
/* linux/arch/arm/mach-s3c2410/bast-irq.c
*
2009-11-13 22:54:14 +00:00
* Copyright 2003 - 2005 Simtec Electronics
2005-04-16 15:20:36 -07:00
* Ben Dooks < ben @ simtec . co . uk >
*
* http : //www.simtec.co.uk/products/EB2410ITX/
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* 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
2005-09-07 17:24:48 +01:00
*/
2005-04-16 15:20:36 -07:00
# include <linux/init.h>
# include <linux/module.h>
# include <linux/ioport.h>
2011-12-21 16:26:03 -08:00
# include <linux/device.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2005-04-16 15:20:36 -07:00
# include <asm/irq.h>
2013-01-01 19:56:20 -08:00
# include <asm/mach-types.h>
2005-04-16 15:20:36 -07:00
# include <asm/mach/irq.h>
2005-09-07 17:24:48 +01:00
2013-01-01 19:56:20 -08:00
# include <mach/hardware.h>
2008-08-05 16:14:15 +01:00
# include <mach/regs-irq.h>
2005-09-07 17:24:48 +01:00
2013-01-01 19:56:20 -08:00
# include "bast.h"
2005-04-16 15:20:36 -07:00
# define irqdbf(x...)
# define irqdbf2(x...)
/* handle PC104 ISA interrupts from the system CPLD */
/* table of ISA irq nos to the relevant mask... zero means
* the irq is not implemented
*/
2016-12-10 15:47:34 +02:00
static const unsigned char bast_pc104_irqmasks [ ] = {
2005-04-16 15:20:36 -07:00
0 , /* 0 */
0 , /* 1 */
0 , /* 2 */
1 , /* 3 */
0 , /* 4 */
2 , /* 5 */
0 , /* 6 */
4 , /* 7 */
0 , /* 8 */
0 , /* 9 */
8 , /* 10 */
0 , /* 11 */
0 , /* 12 */
0 , /* 13 */
0 , /* 14 */
0 , /* 15 */
} ;
2016-12-10 15:47:34 +02:00
static const unsigned char bast_pc104_irqs [ ] = { 3 , 5 , 7 , 10 } ;
2005-04-16 15:20:36 -07:00
static void
2011-01-03 19:15:54 +09:00
bast_pc104_mask ( struct irq_data * data )
2005-04-16 15:20:36 -07:00
{
unsigned long temp ;
temp = __raw_readb ( BAST_VA_PC104_IRQMASK ) ;
2011-01-03 19:15:54 +09:00
temp & = ~ bast_pc104_irqmasks [ data - > irq ] ;
2005-04-16 15:20:36 -07:00
__raw_writeb ( temp , BAST_VA_PC104_IRQMASK ) ;
}
static void
2011-01-03 19:15:54 +09:00
bast_pc104_maskack ( struct irq_data * data )
2005-04-16 15:20:36 -07:00
{
2013-01-01 19:56:20 -08:00
struct irq_desc * desc = irq_desc + BAST_IRQ_ISA ;
2005-09-07 17:24:48 +01:00
2011-01-03 19:15:54 +09:00
bast_pc104_mask ( data ) ;
desc - > irq_data . chip - > irq_ack ( & desc - > irq_data ) ;
2005-04-16 15:20:36 -07:00
}
static void
2011-01-03 19:15:54 +09:00
bast_pc104_unmask ( struct irq_data * data )
2005-04-16 15:20:36 -07:00
{
unsigned long temp ;
temp = __raw_readb ( BAST_VA_PC104_IRQMASK ) ;
2011-01-03 19:15:54 +09:00
temp | = bast_pc104_irqmasks [ data - > irq ] ;
2005-04-16 15:20:36 -07:00
__raw_writeb ( temp , BAST_VA_PC104_IRQMASK ) ;
}
2006-11-23 11:41:32 +00:00
static struct irq_chip bast_pc104_chip = {
2011-01-03 19:15:54 +09:00
. irq_mask = bast_pc104_mask ,
. irq_unmask = bast_pc104_unmask ,
. irq_ack = bast_pc104_maskack
2005-04-16 15:20:36 -07:00
} ;
2015-09-14 10:42:37 +02:00
static void bast_irq_pc104_demux ( struct irq_desc * desc )
2005-04-16 15:20:36 -07:00
{
unsigned int stat ;
unsigned int irqno ;
int i ;
stat = __raw_readb ( BAST_VA_PC104_IRQREQ ) & 0xf ;
2005-09-07 17:24:48 +01:00
if ( unlikely ( stat = = 0 ) ) {
/* ack if we get an irq with nothing (ie, startup) */
2013-01-01 19:56:20 -08:00
desc = irq_desc + BAST_IRQ_ISA ;
2011-01-03 19:15:54 +09:00
desc - > irq_data . chip - > irq_ack ( & desc - > irq_data ) ;
2005-09-07 17:24:48 +01:00
} else {
/* handle the IRQ */
for ( i = 0 ; stat ! = 0 ; i + + , stat > > = 1 ) {
if ( stat & 1 ) {
irqno = bast_pc104_irqs [ i ] ;
2008-10-09 13:36:24 +01:00
generic_handle_irq ( irqno ) ;
2005-09-07 17:24:48 +01:00
}
2005-04-16 15:20:36 -07:00
}
2005-09-07 17:24:48 +01:00
}
}
2005-04-16 15:20:36 -07:00
2005-09-07 17:24:48 +01:00
static __init int bast_irq_init ( void )
{
unsigned int i ;
if ( machine_is_bast ( ) ) {
2009-11-13 22:54:12 +00:00
printk ( KERN_INFO " BAST PC104 IRQ routing, Copyright 2005 Simtec Electronics \n " ) ;
2005-09-07 17:24:48 +01:00
/* zap all the IRQs */
__raw_writeb ( 0x0 , BAST_VA_PC104_IRQMASK ) ;
2013-01-01 19:56:20 -08:00
irq_set_chained_handler ( BAST_IRQ_ISA , bast_irq_pc104_demux ) ;
2005-09-07 17:24:48 +01:00
2006-07-01 22:32:39 +01:00
/* register our IRQs */
2005-09-07 17:24:48 +01:00
for ( i = 0 ; i < 4 ; i + + ) {
unsigned int irqno = bast_pc104_irqs [ i ] ;
2011-03-24 13:35:09 +01:00
irq_set_chip_and_handler ( irqno , & bast_pc104_chip ,
handle_level_irq ) ;
2015-07-27 15:55:13 -05:00
irq_clear_status_flags ( irqno , IRQ_NOREQUEST ) ;
2005-09-07 17:24:48 +01:00
}
2005-04-16 15:20:36 -07:00
}
2005-09-07 17:24:48 +01:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2005-09-07 17:24:48 +01:00
arch_initcall ( bast_irq_init ) ;