2005-04-17 02:20:36 +04:00
/*
* Zalon 53 c7xx device driver .
* By Richard Hirst ( rhirst @ linuxcare . com )
*/
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/module.h>
# include <linux/types.h>
# include <asm/hardware.h>
# include <asm/io.h>
# include "../parisc/gsc.h"
# include "ncr53c8xx.h"
MODULE_AUTHOR ( " Richard Hirst " ) ;
MODULE_DESCRIPTION ( " Bluefish/Zalon 720 SCSI Driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
# define GSC_SCSI_ZALON_OFFSET 0x800
# define IO_MODULE_EIM (1*4)
# define IO_MODULE_DC_ADATA (2*4)
# define IO_MODULE_II_CDATA (3*4)
# define IO_MODULE_IO_COMMAND (12*4)
# define IO_MODULE_IO_STATUS (13*4)
# define IOSTATUS_RY 0x40
# define IOSTATUS_FE 0x80
# define IOIIDATA_SMINT5L 0x40000000
# define IOIIDATA_MINT5EN 0x20000000
# define IOIIDATA_PACKEN 0x10000000
# define IOIIDATA_PREFETCHEN 0x08000000
# define IOIIDATA_IOII 0x00000020
# define CMD_RESET 5
static struct ncr_chip zalon720_chip __initdata = {
. revision_id = 0x0f ,
. burst_max = 3 ,
. offset_max = 8 ,
. nr_divisor = 4 ,
. features = FE_WIDE | FE_DIFF | FE_EHP | FE_MUX | FE_EA ,
} ;
#if 0
/* FIXME:
* Is this function dead code ? or is someone planning on using it in the
* future . The clock = ( int ) pdc_result [ 16 ] does not look correct to
* me . . . I think it should be iodc_data [ 16 ] . Since this cause a compile
* error with the new encapsulated PDC , I ' m not compiling in this function .
* - RB
*/
/* poke SCSI clock out of iodc data */
static u8 iodc_data [ 32 ] __attribute__ ( ( aligned ( 64 ) ) ) ;
static unsigned long pdc_result [ 32 ] __attribute__ ( ( aligned ( 16 ) ) ) = { 0 , 0 , 0 , 0 } ;
static int
lasi_scsi_clock ( void * hpa , int defaultclock )
{
int clock , status ;
status = pdc_iodc_read ( & pdc_result , hpa , 0 , & iodc_data , 32 ) ;
if ( status = = PDC_RET_OK ) {
clock = ( int ) pdc_result [ 16 ] ;
} else {
2008-07-04 10:47:27 +04:00
printk ( KERN_WARNING " %s: pdc_iodc_read returned %d \n " , __func__ , status ) ;
2005-04-17 02:20:36 +04:00
clock = defaultclock ;
}
2008-07-04 10:47:27 +04:00
printk ( KERN_DEBUG " %s: SCSI clock %d \n " , __func__ , clock ) ;
2005-04-17 02:20:36 +04:00
return clock ;
}
# endif
static struct scsi_host_template zalon7xx_template = {
. module = THIS_MODULE ,
. proc_name = " zalon7xx " ,
} ;
static int __init
zalon_probe ( struct parisc_device * dev )
{
struct gsc_irq gsc_irq ;
u32 zalon_vers ;
int error = - ENODEV ;
2006-03-27 23:52:15 +04:00
void __iomem * zalon = ioremap_nocache ( dev - > hpa . start , 4096 ) ;
2005-04-17 02:20:36 +04:00
void __iomem * io_port = zalon + GSC_SCSI_ZALON_OFFSET ;
static int unit = 0 ;
struct Scsi_Host * host ;
struct ncr_device device ;
__raw_writel ( CMD_RESET , zalon + IO_MODULE_IO_COMMAND ) ;
while ( ! ( __raw_readl ( zalon + IO_MODULE_IO_STATUS ) & IOSTATUS_RY ) )
cpu_relax ( ) ;
__raw_writel ( IOIIDATA_MINT5EN | IOIIDATA_PACKEN | IOIIDATA_PREFETCHEN ,
zalon + IO_MODULE_II_CDATA ) ;
/* XXX: Save the Zalon version for bug workarounds? */
zalon_vers = ( __raw_readl ( zalon + IO_MODULE_II_CDATA ) > > 24 ) & 0x07 ;
/* Setup the interrupts first.
* * Later on request_irq ( ) will register the handler .
*/
dev - > irq = gsc_alloc_irq ( & gsc_irq ) ;
2008-07-04 10:47:27 +04:00
printk ( KERN_INFO " %s: Zalon version %d, IRQ %d \n " , __func__ ,
2005-04-17 02:20:36 +04:00
zalon_vers , dev - > irq ) ;
__raw_writel ( gsc_irq . txn_addr | gsc_irq . txn_data , zalon + IO_MODULE_EIM ) ;
if ( zalon_vers = = 0 )
2008-07-04 10:47:27 +04:00
printk ( KERN_WARNING " %s: Zalon 1.1 or earlier \n " , __func__ ) ;
2005-04-17 02:20:36 +04:00
memset ( & device , 0 , sizeof ( struct ncr_device ) ) ;
/* The following three are needed before any other access. */
__raw_writeb ( 0x20 , io_port + 0x38 ) ; /* DCNTL_REG, EA */
__raw_writeb ( 0x04 , io_port + 0x1b ) ; /* CTEST0_REG, EHP */
__raw_writeb ( 0x80 , io_port + 0x22 ) ; /* CTEST4_REG, MUX */
/* Initialise ncr_device structure with items required by ncr_attach. */
device . chip = zalon720_chip ;
device . host_id = 7 ;
device . dev = & dev - > dev ;
2005-10-22 06:36:40 +04:00
device . slot . base = dev - > hpa . start + GSC_SCSI_ZALON_OFFSET ;
2005-04-17 02:20:36 +04:00
device . slot . base_v = io_port ;
device . slot . irq = dev - > irq ;
device . differential = 2 ;
host = ncr_attach ( & zalon7xx_template , unit , & device ) ;
if ( ! host )
2009-06-24 23:55:22 +04:00
return - ENODEV ;
2005-04-17 02:20:36 +04:00
2006-07-02 06:29:42 +04:00
if ( request_irq ( dev - > irq , ncr53c8xx_intr , IRQF_SHARED , " zalon " , host ) ) {
2009-01-13 23:14:51 +03:00
dev_printk ( KERN_ERR , & dev - > dev , " irq problem with %d, detaching \n " ,
2008-12-04 00:41:36 +03:00
dev - > irq ) ;
2005-04-17 02:20:36 +04:00
goto fail ;
}
unit + + ;
dev_set_drvdata ( & dev - > dev , host ) ;
error = scsi_add_host ( host , & dev - > dev ) ;
if ( error )
goto fail_free_irq ;
scsi_scan_host ( host ) ;
return 0 ;
fail_free_irq :
free_irq ( dev - > irq , host ) ;
fail :
ncr53c8xx_release ( host ) ;
return error ;
}
static struct parisc_device_id zalon_tbl [ ] = {
{ HPHW_A_DMA , HVERSION_REV_ANY_ID , HVERSION_ANY_ID , 0x00089 } ,
{ 0 , }
} ;
MODULE_DEVICE_TABLE ( parisc , zalon_tbl ) ;
static int __exit zalon_remove ( struct parisc_device * dev )
{
struct Scsi_Host * host = dev_get_drvdata ( & dev - > dev ) ;
scsi_remove_host ( host ) ;
ncr53c8xx_release ( host ) ;
free_irq ( dev - > irq , host ) ;
return 0 ;
}
static struct parisc_driver zalon_driver = {
. name = " zalon " ,
. id_table = zalon_tbl ,
. probe = zalon_probe ,
. remove = __devexit_p ( zalon_remove ) ,
} ;
static int __init zalon7xx_init ( void )
{
int ret = ncr53c8xx_init ( ) ;
if ( ! ret )
ret = register_parisc_driver ( & zalon_driver ) ;
if ( ret )
ncr53c8xx_exit ( ) ;
return ret ;
}
static void __exit zalon7xx_exit ( void )
{
unregister_parisc_driver ( & zalon_driver ) ;
ncr53c8xx_exit ( ) ;
}
module_init ( zalon7xx_init ) ;
module_exit ( zalon7xx_exit ) ;