1*c27d85f3SThomas Bogendoerfer /* -*- mode: c; c-basic-offset: 8 -*- */ 2*c27d85f3SThomas Bogendoerfer 3*c27d85f3SThomas Bogendoerfer /* SNI RM driver 4*c27d85f3SThomas Bogendoerfer * 5*c27d85f3SThomas Bogendoerfer * Copyright (C) 2001 by James.Bottomley@HansenPartnership.com 6*c27d85f3SThomas Bogendoerfer **----------------------------------------------------------------------------- 7*c27d85f3SThomas Bogendoerfer ** 8*c27d85f3SThomas Bogendoerfer ** This program is free software; you can redistribute it and/or modify 9*c27d85f3SThomas Bogendoerfer ** it under the terms of the GNU General Public License as published by 10*c27d85f3SThomas Bogendoerfer ** the Free Software Foundation; either version 2 of the License, or 11*c27d85f3SThomas Bogendoerfer ** (at your option) any later version. 12*c27d85f3SThomas Bogendoerfer ** 13*c27d85f3SThomas Bogendoerfer ** This program is distributed in the hope that it will be useful, 14*c27d85f3SThomas Bogendoerfer ** but WITHOUT ANY WARRANTY; without even the implied warranty of 15*c27d85f3SThomas Bogendoerfer ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*c27d85f3SThomas Bogendoerfer ** GNU General Public License for more details. 17*c27d85f3SThomas Bogendoerfer ** 18*c27d85f3SThomas Bogendoerfer ** You should have received a copy of the GNU General Public License 19*c27d85f3SThomas Bogendoerfer ** along with this program; if not, write to the Free Software 20*c27d85f3SThomas Bogendoerfer ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21*c27d85f3SThomas Bogendoerfer ** 22*c27d85f3SThomas Bogendoerfer **----------------------------------------------------------------------------- 23*c27d85f3SThomas Bogendoerfer */ 24*c27d85f3SThomas Bogendoerfer 25*c27d85f3SThomas Bogendoerfer /* 26*c27d85f3SThomas Bogendoerfer * Based on lasi700.c 27*c27d85f3SThomas Bogendoerfer */ 28*c27d85f3SThomas Bogendoerfer 29*c27d85f3SThomas Bogendoerfer #include <linux/kernel.h> 30*c27d85f3SThomas Bogendoerfer #include <linux/module.h> 31*c27d85f3SThomas Bogendoerfer #include <linux/init.h> 32*c27d85f3SThomas Bogendoerfer #include <linux/types.h> 33*c27d85f3SThomas Bogendoerfer #include <linux/stat.h> 34*c27d85f3SThomas Bogendoerfer #include <linux/mm.h> 35*c27d85f3SThomas Bogendoerfer #include <linux/blkdev.h> 36*c27d85f3SThomas Bogendoerfer #include <linux/sched.h> 37*c27d85f3SThomas Bogendoerfer #include <linux/ioport.h> 38*c27d85f3SThomas Bogendoerfer #include <linux/dma-mapping.h> 39*c27d85f3SThomas Bogendoerfer #include <linux/platform_device.h> 40*c27d85f3SThomas Bogendoerfer 41*c27d85f3SThomas Bogendoerfer #include <asm/page.h> 42*c27d85f3SThomas Bogendoerfer #include <asm/pgtable.h> 43*c27d85f3SThomas Bogendoerfer #include <asm/irq.h> 44*c27d85f3SThomas Bogendoerfer #include <asm/delay.h> 45*c27d85f3SThomas Bogendoerfer 46*c27d85f3SThomas Bogendoerfer #include <scsi/scsi_host.h> 47*c27d85f3SThomas Bogendoerfer #include <scsi/scsi_device.h> 48*c27d85f3SThomas Bogendoerfer #include <scsi/scsi_transport.h> 49*c27d85f3SThomas Bogendoerfer #include <scsi/scsi_transport_spi.h> 50*c27d85f3SThomas Bogendoerfer 51*c27d85f3SThomas Bogendoerfer #include "53c700.h" 52*c27d85f3SThomas Bogendoerfer 53*c27d85f3SThomas Bogendoerfer MODULE_AUTHOR("Thomas Bogend�rfer"); 54*c27d85f3SThomas Bogendoerfer MODULE_DESCRIPTION("SNI RM 53c710 SCSI Driver"); 55*c27d85f3SThomas Bogendoerfer MODULE_LICENSE("GPL"); 56*c27d85f3SThomas Bogendoerfer 57*c27d85f3SThomas Bogendoerfer #define SNIRM710_CLOCK 32 58*c27d85f3SThomas Bogendoerfer 59*c27d85f3SThomas Bogendoerfer static struct scsi_host_template snirm710_template = { 60*c27d85f3SThomas Bogendoerfer .name = "SNI RM SCSI 53c710", 61*c27d85f3SThomas Bogendoerfer .proc_name = "snirm_53c710", 62*c27d85f3SThomas Bogendoerfer .this_id = 7, 63*c27d85f3SThomas Bogendoerfer .module = THIS_MODULE, 64*c27d85f3SThomas Bogendoerfer }; 65*c27d85f3SThomas Bogendoerfer 66*c27d85f3SThomas Bogendoerfer static int __init snirm710_probe(struct platform_device *dev) 67*c27d85f3SThomas Bogendoerfer { 68*c27d85f3SThomas Bogendoerfer unsigned long base; 69*c27d85f3SThomas Bogendoerfer struct NCR_700_Host_Parameters *hostdata; 70*c27d85f3SThomas Bogendoerfer struct Scsi_Host *host; 71*c27d85f3SThomas Bogendoerfer struct resource *res; 72*c27d85f3SThomas Bogendoerfer 73*c27d85f3SThomas Bogendoerfer res = platform_get_resource(dev, IORESOURCE_MEM, 0); 74*c27d85f3SThomas Bogendoerfer if (!res) 75*c27d85f3SThomas Bogendoerfer return -ENODEV; 76*c27d85f3SThomas Bogendoerfer 77*c27d85f3SThomas Bogendoerfer base = res->start; 78*c27d85f3SThomas Bogendoerfer hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); 79*c27d85f3SThomas Bogendoerfer if (!hostdata) { 80*c27d85f3SThomas Bogendoerfer printk(KERN_ERR "%s: Failed to allocate host data\n", 81*c27d85f3SThomas Bogendoerfer dev->dev.bus_id); 82*c27d85f3SThomas Bogendoerfer return -ENOMEM; 83*c27d85f3SThomas Bogendoerfer } 84*c27d85f3SThomas Bogendoerfer 85*c27d85f3SThomas Bogendoerfer hostdata->dev = &dev->dev; 86*c27d85f3SThomas Bogendoerfer dma_set_mask(&dev->dev, DMA_32BIT_MASK); 87*c27d85f3SThomas Bogendoerfer hostdata->base = ioremap_nocache(CPHYSADDR(base), 0x100); 88*c27d85f3SThomas Bogendoerfer hostdata->differential = 0; 89*c27d85f3SThomas Bogendoerfer 90*c27d85f3SThomas Bogendoerfer hostdata->clock = SNIRM710_CLOCK; 91*c27d85f3SThomas Bogendoerfer hostdata->force_le_on_be = 1; 92*c27d85f3SThomas Bogendoerfer hostdata->chip710 = 1; 93*c27d85f3SThomas Bogendoerfer hostdata->burst_length = 4; 94*c27d85f3SThomas Bogendoerfer 95*c27d85f3SThomas Bogendoerfer host = NCR_700_detect(&snirm710_template, hostdata, &dev->dev); 96*c27d85f3SThomas Bogendoerfer if (!host) 97*c27d85f3SThomas Bogendoerfer goto out_kfree; 98*c27d85f3SThomas Bogendoerfer host->this_id = 7; 99*c27d85f3SThomas Bogendoerfer host->base = base; 100*c27d85f3SThomas Bogendoerfer host->irq = platform_get_irq(dev, 0); 101*c27d85f3SThomas Bogendoerfer if(request_irq(host->irq, NCR_700_intr, SA_SHIRQ, "snirm710", host)) { 102*c27d85f3SThomas Bogendoerfer printk(KERN_ERR "snirm710: request_irq failed!\n"); 103*c27d85f3SThomas Bogendoerfer goto out_put_host; 104*c27d85f3SThomas Bogendoerfer } 105*c27d85f3SThomas Bogendoerfer 106*c27d85f3SThomas Bogendoerfer dev_set_drvdata(&dev->dev, host); 107*c27d85f3SThomas Bogendoerfer scsi_scan_host(host); 108*c27d85f3SThomas Bogendoerfer 109*c27d85f3SThomas Bogendoerfer return 0; 110*c27d85f3SThomas Bogendoerfer 111*c27d85f3SThomas Bogendoerfer out_put_host: 112*c27d85f3SThomas Bogendoerfer scsi_host_put(host); 113*c27d85f3SThomas Bogendoerfer out_kfree: 114*c27d85f3SThomas Bogendoerfer iounmap(hostdata->base); 115*c27d85f3SThomas Bogendoerfer kfree(hostdata); 116*c27d85f3SThomas Bogendoerfer return -ENODEV; 117*c27d85f3SThomas Bogendoerfer } 118*c27d85f3SThomas Bogendoerfer 119*c27d85f3SThomas Bogendoerfer static int __exit snirm710_driver_remove(struct platform_device *dev) 120*c27d85f3SThomas Bogendoerfer { 121*c27d85f3SThomas Bogendoerfer struct Scsi_Host *host = dev_get_drvdata(&dev->dev); 122*c27d85f3SThomas Bogendoerfer struct NCR_700_Host_Parameters *hostdata = 123*c27d85f3SThomas Bogendoerfer (struct NCR_700_Host_Parameters *)host->hostdata[0]; 124*c27d85f3SThomas Bogendoerfer 125*c27d85f3SThomas Bogendoerfer scsi_remove_host(host); 126*c27d85f3SThomas Bogendoerfer NCR_700_release(host); 127*c27d85f3SThomas Bogendoerfer free_irq(host->irq, host); 128*c27d85f3SThomas Bogendoerfer iounmap(hostdata->base); 129*c27d85f3SThomas Bogendoerfer kfree(hostdata); 130*c27d85f3SThomas Bogendoerfer 131*c27d85f3SThomas Bogendoerfer return 0; 132*c27d85f3SThomas Bogendoerfer } 133*c27d85f3SThomas Bogendoerfer 134*c27d85f3SThomas Bogendoerfer static struct platform_driver snirm710_driver = { 135*c27d85f3SThomas Bogendoerfer .probe = snirm710_probe, 136*c27d85f3SThomas Bogendoerfer .remove = __devexit_p(snirm710_driver_remove), 137*c27d85f3SThomas Bogendoerfer .driver = { 138*c27d85f3SThomas Bogendoerfer .name = "snirm_53c710", 139*c27d85f3SThomas Bogendoerfer }, 140*c27d85f3SThomas Bogendoerfer }; 141*c27d85f3SThomas Bogendoerfer 142*c27d85f3SThomas Bogendoerfer static int __init snirm710_init(void) 143*c27d85f3SThomas Bogendoerfer { 144*c27d85f3SThomas Bogendoerfer int err; 145*c27d85f3SThomas Bogendoerfer 146*c27d85f3SThomas Bogendoerfer if ((err = platform_driver_register(&snirm710_driver))) { 147*c27d85f3SThomas Bogendoerfer printk(KERN_ERR "Driver registration failed\n"); 148*c27d85f3SThomas Bogendoerfer return err; 149*c27d85f3SThomas Bogendoerfer } 150*c27d85f3SThomas Bogendoerfer return 0; 151*c27d85f3SThomas Bogendoerfer } 152*c27d85f3SThomas Bogendoerfer 153*c27d85f3SThomas Bogendoerfer static void __exit snirm710_exit(void) 154*c27d85f3SThomas Bogendoerfer { 155*c27d85f3SThomas Bogendoerfer platform_driver_unregister(&snirm710_driver); 156*c27d85f3SThomas Bogendoerfer } 157*c27d85f3SThomas Bogendoerfer 158*c27d85f3SThomas Bogendoerfer module_init(snirm710_init); 159*c27d85f3SThomas Bogendoerfer module_exit(snirm710_exit); 160