2005-04-17 02:20:36 +04:00
/*
2008-02-02 01:09:33 +03:00
* Amiga Gayle IDE Driver
2005-04-17 02:20:36 +04:00
*
* Created 9 Jul 1997 by Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file COPYING in the main directory of this archive for
* more details .
*/
# include <linux/types.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
# include <linux/blkdev.h>
# include <linux/ide.h>
# include <linux/init.h>
# include <linux/zorro.h>
2008-06-10 22:56:38 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <asm/setup.h>
# include <asm/amigahw.h>
# include <asm/amigaints.h>
# include <asm/amigayle.h>
/*
* Bases of the IDE interfaces
*/
# define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */
# define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */
2008-07-23 21:55:56 +04:00
# define GAYLE_IDEREG_SIZE 0x2000
2005-04-17 02:20:36 +04:00
/*
* Offsets from one of the above bases
*/
# define GAYLE_CONTROL 0x101a
/*
* These are at different offsets from the base
*/
# define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */
# define GAYLE_IRQ_1200 0xda9000 /* interrupt */
/*
* Offset of the secondary port for IDE doublers
* Note that GAYLE_CONTROL is NOT available then !
*/
# define GAYLE_NEXT_PORT 0x1000
# define GAYLE_NUM_HWIFS 2
# define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \
GAYLE_NUM_HWIFS - 1 )
# define GAYLE_HAS_CONTROL_REG (!ide_doubler)
2008-06-10 22:56:38 +04:00
2008-07-15 23:21:47 +04:00
static int ide_doubler ;
2008-04-27 17:38:30 +04:00
module_param_named ( doubler , ide_doubler , bool , 0 ) ;
MODULE_PARM_DESC ( doubler , " enable support for IDE doublers " ) ;
2005-04-17 02:20:36 +04:00
/*
* Check and acknowledge the interrupt status
*/
static int gayle_ack_intr_a4000 ( ide_hwif_t * hwif )
{
unsigned char ch ;
2008-04-27 17:38:32 +04:00
ch = z_readb ( hwif - > io_ports . irq_addr ) ;
2005-04-17 02:20:36 +04:00
if ( ! ( ch & GAYLE_IRQ_IDE ) )
return 0 ;
return 1 ;
}
static int gayle_ack_intr_a1200 ( ide_hwif_t * hwif )
{
unsigned char ch ;
2008-04-27 17:38:32 +04:00
ch = z_readb ( hwif - > io_ports . irq_addr ) ;
2005-04-17 02:20:36 +04:00
if ( ! ( ch & GAYLE_IRQ_IDE ) )
return 0 ;
2008-04-27 17:38:32 +04:00
( void ) z_readb ( hwif - > io_ports . status_addr ) ;
z_writeb ( 0x7c , hwif - > io_ports . irq_addr ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
2008-02-06 04:57:50 +03:00
static void __init gayle_setup_ports ( hw_regs_t * hw , unsigned long base ,
unsigned long ctl , unsigned long irq_port ,
2008-02-11 02:32:14 +03:00
ide_ack_intr_t * ack_intr )
2008-02-06 04:57:50 +03:00
{
int i ;
memset ( hw , 0 , sizeof ( * hw ) ) ;
2008-04-27 17:38:32 +04:00
hw - > io_ports . data_addr = base ;
2008-02-06 04:57:50 +03:00
for ( i = 1 ; i < 8 ; i + + )
2008-04-27 17:38:32 +04:00
hw - > io_ports_array [ i ] = base + 2 + i * 4 ;
2008-02-06 04:57:50 +03:00
2008-04-27 17:38:32 +04:00
hw - > io_ports . ctl_addr = ctl ;
hw - > io_ports . irq_addr = irq_port ;
2008-02-06 04:57:50 +03:00
hw - > irq = IRQ_AMIGA_PORTS ;
hw - > ack_intr = ack_intr ;
2008-06-10 22:56:37 +04:00
hw - > chipset = ide_generic ;
2008-02-06 04:57:50 +03:00
}
2008-12-29 22:27:33 +03:00
static const struct ide_port_info gayle_port_info = {
2009-03-27 14:46:23 +03:00
. host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE |
IDE_HFLAG_NO_DMA ,
2009-03-27 14:46:27 +03:00
. irq_flags = IRQF_SHARED ,
2008-12-29 22:27:33 +03:00
} ;
2005-04-17 02:20:36 +04:00
/*
* Probe for a Gayle IDE interface ( and optionally for an IDE doubler )
*/
2008-01-26 22:13:07 +03:00
static int __init gayle_init ( void )
2005-04-17 02:20:36 +04:00
{
2008-07-23 21:55:56 +04:00
unsigned long phys_base , res_start , res_n ;
unsigned long base , ctrlport , irqport ;
ide_ack_intr_t * ack_intr ;
2008-07-25 00:53:34 +04:00
int a4000 , i , rc ;
2008-07-23 21:55:50 +04:00
hw_regs_t hw [ GAYLE_NUM_HWIFS ] , * hws [ ] = { NULL , NULL , NULL , NULL } ;
2005-04-17 02:20:36 +04:00
if ( ! MACH_IS_AMIGA )
2008-01-26 22:13:07 +03:00
return - ENODEV ;
2005-04-17 02:20:36 +04:00
if ( ( a4000 = AMIGAHW_PRESENT ( A4000_IDE ) ) | | AMIGAHW_PRESENT ( A1200_IDE ) )
goto found ;
# ifdef CONFIG_ZORRO
if ( zorro_find_device ( ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE ,
NULL ) )
goto found ;
# endif
2008-01-26 22:13:07 +03:00
return - ENODEV ;
2005-04-17 02:20:36 +04:00
found :
2008-01-26 22:13:09 +03:00
printk ( KERN_INFO " ide: Gayle IDE controller (A%d style%s) \n " ,
a4000 ? 4000 : 1200 ,
2009-03-31 22:15:26 +04:00
ide_doubler ? " , IDE doubler " : " " ) ;
2008-01-26 22:13:09 +03:00
2005-04-17 02:20:36 +04:00
if ( a4000 ) {
phys_base = GAYLE_BASE_4000 ;
irqport = ( unsigned long ) ZTWO_VADDR ( GAYLE_IRQ_4000 ) ;
ack_intr = gayle_ack_intr_a4000 ;
} else {
phys_base = GAYLE_BASE_1200 ;
irqport = ( unsigned long ) ZTWO_VADDR ( GAYLE_IRQ_1200 ) ;
ack_intr = gayle_ack_intr_a1200 ;
}
res_start = ( ( unsigned long ) phys_base ) & ~ ( GAYLE_NEXT_PORT - 1 ) ;
res_n = GAYLE_IDEREG_SIZE ;
if ( ! request_mem_region ( res_start , res_n , " IDE " ) )
2008-07-23 21:55:56 +04:00
return - EBUSY ;
2005-04-17 02:20:36 +04:00
2008-07-23 21:55:56 +04:00
for ( i = 0 ; i < GAYLE_NUM_PROBE_HWIFS ; i + + ) {
base = ( unsigned long ) ZTWO_VADDR ( phys_base + i * GAYLE_NEXT_PORT ) ;
2005-04-17 02:20:36 +04:00
ctrlport = GAYLE_HAS_CONTROL_REG ? ( base + GAYLE_CONTROL ) : 0 ;
2008-07-23 21:55:50 +04:00
gayle_setup_ports ( & hw [ i ] , base , ctrlport , irqport , ack_intr ) ;
2005-04-17 02:20:36 +04:00
2008-07-23 21:55:57 +04:00
hws [ i ] = & hw [ i ] ;
2005-04-17 02:20:36 +04:00
}
2008-01-26 22:13:06 +03:00
2008-12-29 22:27:33 +03:00
rc = ide_host_add ( & gayle_port_info , hws , NULL ) ;
2008-07-25 00:53:34 +04:00
if ( rc )
release_mem_region ( res_start , res_n ) ;
return rc ;
2005-04-17 02:20:36 +04:00
}
2008-01-26 22:13:07 +03:00
module_init ( gayle_init ) ;
2008-04-02 23:22:04 +04:00
MODULE_LICENSE ( " GPL " ) ;