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>
2009-12-08 22:12:20 +03:00
# include <linux/platform_device.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>
/*
* 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
2012-01-13 03:02:20 +04:00
static bool 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
*/
2009-06-15 20:52:58 +04:00
static int gayle_test_irq ( ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
2009-12-08 22:12:20 +03:00
unsigned char ch ;
2005-04-17 02:20:36 +04:00
2009-12-08 22:12:20 +03:00
ch = z_readb ( hwif - > io_ports . irq_addr ) ;
if ( ! ( ch & GAYLE_IRQ_IDE ) )
return 0 ;
return 1 ;
2005-04-17 02:20:36 +04:00
}
2009-06-15 20:52:57 +04:00
static void gayle_a1200_clear_irq ( ide_drive_t * drive )
2005-04-17 02:20:36 +04:00
{
2009-12-08 22:12:20 +03:00
ide_hwif_t * hwif = drive - > hwif ;
2005-04-17 02:20:36 +04:00
2009-12-08 22:12:20 +03: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
}
2009-05-17 21:12:25 +04:00
static void __init gayle_setup_ports ( struct ide_hw * hw , unsigned long base ,
2009-06-15 20:52:58 +04:00
unsigned long ctl , unsigned long irq_port )
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 ;
}
2009-06-15 20:52:58 +04:00
static const struct ide_port_ops gayle_a4000_port_ops = {
. test_irq = gayle_test_irq ,
} ;
2009-06-15 20:52:57 +04:00
static const struct ide_port_ops gayle_a1200_port_ops = {
. clear_irq = gayle_a1200_clear_irq ,
2009-06-15 20:52:58 +04:00
. test_irq = gayle_test_irq ,
2009-06-15 20:52:57 +04: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 ,
2009-05-17 21:12:22 +04:00
. chipset = ide_generic ,
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 )
*/
2009-12-08 22:12:20 +03:00
static int __init amiga_gayle_ide_probe ( struct platform_device * pdev )
2005-04-17 02:20:36 +04:00
{
2009-12-08 22:12:20 +03:00
struct resource * res ;
struct gayle_ide_platform_data * pdata ;
unsigned long base , ctrlport , irqport ;
unsigned int i ;
int error ;
struct ide_hw hw [ GAYLE_NUM_HWIFS ] , * hws [ GAYLE_NUM_HWIFS ] ;
struct ide_port_info d = gayle_port_info ;
struct ide_host * host ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! res )
return - ENODEV ;
if ( ! request_mem_region ( res - > start , resource_size ( res ) , " IDE " ) )
return - EBUSY ;
2013-07-30 12:16:47 +04:00
pdata = dev_get_platdata ( & pdev - > dev ) ;
2009-12-08 22:12:20 +03:00
pr_info ( " ide: Gayle IDE controller (A%u style%s) \n " ,
pdata - > explicit_ack ? 1200 : 4000 ,
ide_doubler ? " , IDE doubler " : " " ) ;
base = ( unsigned long ) ZTWO_VADDR ( pdata - > base ) ;
ctrlport = 0 ;
irqport = ( unsigned long ) ZTWO_VADDR ( pdata - > irqport ) ;
if ( pdata - > explicit_ack )
d . port_ops = & gayle_a1200_port_ops ;
else
d . port_ops = & gayle_a4000_port_ops ;
for ( i = 0 ; i < GAYLE_NUM_PROBE_HWIFS ; i + + , base + = GAYLE_NEXT_PORT ) {
if ( GAYLE_HAS_CONTROL_REG )
ctrlport = base + GAYLE_CONTROL ;
gayle_setup_ports ( & hw [ i ] , base , ctrlport , irqport ) ;
hws [ i ] = & hw [ i ] ;
2005-04-17 02:20:36 +04:00
}
2009-12-08 22:12:20 +03:00
error = ide_host_add ( & d , hws , i , & host ) ;
if ( error )
goto out ;
2005-04-17 02:20:36 +04:00
2009-12-08 22:12:20 +03:00
platform_set_drvdata ( pdev , host ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
2009-12-08 22:12:20 +03:00
out :
release_mem_region ( res - > start , resource_size ( res ) ) ;
return error ;
}
static int __exit amiga_gayle_ide_remove ( struct platform_device * pdev )
{
struct ide_host * host = platform_get_drvdata ( pdev ) ;
struct resource * res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
ide_host_remove ( host ) ;
release_mem_region ( res - > start , resource_size ( res ) ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2009-12-08 22:12:20 +03:00
static struct platform_driver amiga_gayle_ide_driver = {
. remove = __exit_p ( amiga_gayle_ide_remove ) ,
. driver = {
. name = " amiga-gayle-ide " ,
} ,
} ;
2005-04-17 02:20:36 +04:00
2013-03-04 20:27:36 +04:00
module_platform_driver_probe ( amiga_gayle_ide_driver , amiga_gayle_ide_probe ) ;
2008-04-02 23:22:04 +04:00
MODULE_LICENSE ( " GPL " ) ;
2009-12-08 22:12:20 +03:00
MODULE_ALIAS ( " platform:amiga-gayle-ide " ) ;