2005-04-17 02:20:36 +04:00
/*
* Basic EISA bus support for the SGI Indigo - 2.
*
* ( C ) 2002 Pascal Dameme < netinet @ freesurf . fr >
2013-01-22 15:59:30 +04:00
* and Marc Zyngier < mzyngier @ freesurf . fr >
2005-04-17 02:20:36 +04:00
*
* This code is released under both the GPL version 2 and BSD
* licenses . Either license may be used .
*
* This code offers a very basic support for this EISA bus present in
* the SGI Indigo - 2. It currently only supports PIO ( forget about DMA
* for the time being ) . This is enough for a low - end ethernet card ,
* but forget about your favorite SCSI card . . .
*
* TODO :
* - Fix bugs . . .
* - Add ISA support
* - Add DMA ( yeah , right . . . ) .
* - Fix more bugs .
*/
# include <linux/eisa.h>
# include <linux/types.h>
# include <linux/init.h>
# include <linux/irq.h>
# include <linux/kernel_stat.h>
# include <linux/signal.h>
# include <linux/sched.h>
# include <linux/interrupt.h>
# include <linux/delay.h>
2005-08-31 19:55:16 +04:00
# include <asm/io.h>
2005-04-17 02:20:36 +04:00
# include <asm/irq.h>
# include <asm/mipsregs.h>
# include <asm/addrspace.h>
# include <asm/processor.h>
# include <asm/sgi/ioc.h>
# include <asm/sgi/mc.h>
# include <asm/sgi/ip22.h>
2007-11-23 22:34:16 +03:00
# include <asm/i8259.h>
2005-04-17 02:20:36 +04:00
2005-08-31 19:55:16 +04:00
/* I2 has four EISA slots. */
# define IP22_EISA_MAX_SLOTS 4
2013-01-22 15:59:30 +04:00
# define EISA_MAX_IRQ 16
2005-04-17 02:20:36 +04:00
2013-01-22 15:59:30 +04:00
# define EIU_MODE_REG 0x0001ffc0
# define EIU_STAT_REG 0x0001ffc4
# define EIU_PREMPT_REG 0x0001ffc8
# define EIU_QUIET_REG 0x0001ffcc
# define EIU_INTRPT_ACK 0x00010004
2005-08-31 19:55:16 +04:00
static char __init * decode_eisa_sig ( unsigned long addr )
2005-04-17 02:20:36 +04:00
{
2009-11-23 14:53:37 +03:00
static char sig_str [ EISA_SIG_LEN ] __initdata ;
2005-08-31 19:55:16 +04:00
u8 sig [ 4 ] ;
2009-11-23 14:53:37 +03:00
u16 rev ;
2005-08-31 19:55:16 +04:00
int i ;
for ( i = 0 ; i < 4 ; i + + ) {
2007-10-12 02:46:15 +04:00
sig [ i ] = inb ( addr + i ) ;
2005-04-17 02:20:36 +04:00
2005-08-31 19:55:16 +04:00
if ( ! i & & ( sig [ 0 ] & 0x80 ) )
return NULL ;
}
2005-04-17 02:20:36 +04:00
sig_str [ 0 ] = ( ( sig [ 0 ] > > 2 ) & 0x1f ) + ( ' A ' - 1 ) ;
sig_str [ 1 ] = ( ( ( sig [ 0 ] & 3 ) < < 3 ) | ( sig [ 1 ] > > 5 ) ) + ( ' A ' - 1 ) ;
sig_str [ 2 ] = ( sig [ 1 ] & 0x1f ) + ( ' A ' - 1 ) ;
rev = ( sig [ 2 ] < < 8 ) | sig [ 3 ] ;
sprintf ( sig_str + 3 , " %04X " , rev ) ;
return sig_str ;
}
2006-10-07 22:44:33 +04:00
static irqreturn_t ip22_eisa_intr ( int irq , void * dev_id )
2005-04-17 02:20:36 +04:00
{
2012-09-06 12:02:40 +04:00
u8 eisa_irq = inb ( EIU_INTRPT_ACK ) ;
2005-04-17 02:20:36 +04:00
2012-09-06 12:02:40 +04:00
inb ( EISA_DMA1_STATUS ) ;
inb ( EISA_DMA2_STATUS ) ;
2005-04-17 02:20:36 +04:00
2005-08-31 19:55:16 +04:00
if ( eisa_irq < EISA_MAX_IRQ ) {
2006-10-07 22:44:33 +04:00
do_IRQ ( eisa_irq ) ;
2005-08-31 19:55:16 +04:00
return IRQ_HANDLED ;
}
/* Oops, Bad Stuff Happened... */
printk ( KERN_ERR " eisa_irq %d out of bound \n " , eisa_irq ) ;
outb ( 0x20 , EISA_INT2_CTRL ) ;
outb ( 0x20 , EISA_INT1_CTRL ) ;
2006-10-07 22:44:33 +04:00
2005-08-31 19:55:16 +04:00
return IRQ_NONE ;
2005-04-17 02:20:36 +04:00
}
static struct irqaction eisa_action = {
. handler = ip22_eisa_intr ,
. name = " EISA " ,
} ;
int __init ip22_eisa_init ( void )
{
int i , c ;
char * str ;
2005-09-04 02:56:17 +04:00
2005-04-17 02:20:36 +04:00
if ( ! ( sgimc - > systemid & SGIMC_SYSID_EPRESENT ) ) {
printk ( KERN_INFO " EISA: bus not present. \n " ) ;
return 1 ;
}
printk ( KERN_INFO " EISA: Probing bus... \n " ) ;
2005-08-31 19:55:16 +04:00
for ( c = 0 , i = 1 ; i < = IP22_EISA_MAX_SLOTS ; i + + ) {
if ( ( str = decode_eisa_sig ( 0x1000 * i + EISA_VENDOR_ID_OFFSET ) ) ) {
2005-04-17 02:20:36 +04:00
printk ( KERN_INFO " EISA: slot %d : %s detected. \n " ,
i , str ) ;
c + + ;
}
}
printk ( KERN_INFO " EISA: Detected %d card%s. \n " , c , c < 2 ? " " : " s " ) ;
# ifdef CONFIG_ISA
printk ( KERN_INFO " ISA support compiled in. \n " ) ;
# endif
/* Warning : BlackMagicAhead(tm).
Please wave your favorite dead chicken over the busses */
/* First say hello to the EIU */
2005-08-31 19:55:16 +04:00
outl ( 0x0000FFFF , EIU_PREMPT_REG ) ;
outl ( 1 , EIU_QUIET_REG ) ;
outl ( 0x40f3c07F , EIU_MODE_REG ) ;
2005-04-17 02:20:36 +04:00
/* Now be nice to the EISA chipset */
2005-08-31 19:55:16 +04:00
outb ( 1 , EISA_EXT_NMI_RESET_CTRL ) ;
udelay ( 50 ) ; /* Wait long enough for the dust to settle */
outb ( 0 , EISA_EXT_NMI_RESET_CTRL ) ;
outb ( 0 , EISA_DMA2_WRITE_SINGLE ) ;
2005-04-17 02:20:36 +04:00
2007-11-23 22:34:16 +03:00
init_i8259_irqs ( ) ;
2005-04-17 02:20:36 +04:00
/* Cannot use request_irq because of kmalloc not being ready at such
* an early stage . Yes , I ' ve been bitten . . . */
setup_irq ( SGI_EISA_IRQ , & eisa_action ) ;
EISA_bus = 1 ;
return 0 ;
}