1a16efc1cSKars de Jong /* 2a16efc1cSKars de Jong * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux. 3a16efc1cSKars de Jong * Amiga Technologies A4000T SCSI controller. 4a16efc1cSKars de Jong * 5a16efc1cSKars de Jong * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk> 6a16efc1cSKars de Jong * plus modifications of the 53c7xx.c driver to support the Amiga. 7a16efc1cSKars de Jong * 8a16efc1cSKars de Jong * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org> 9a16efc1cSKars de Jong */ 10a16efc1cSKars de Jong 11a16efc1cSKars de Jong #include <linux/module.h> 12a16efc1cSKars de Jong #include <linux/platform_device.h> 13a16efc1cSKars de Jong #include <linux/init.h> 14a16efc1cSKars de Jong #include <linux/interrupt.h> 15*5a0e3ad6STejun Heo #include <linux/slab.h> 1696249cf9SGeert Uytterhoeven #include <asm/amigahw.h> 17a16efc1cSKars de Jong #include <asm/amigaints.h> 18a16efc1cSKars de Jong #include <scsi/scsi_host.h> 19a16efc1cSKars de Jong #include <scsi/scsi_transport_spi.h> 20a16efc1cSKars de Jong 21a16efc1cSKars de Jong #include "53c700.h" 22a16efc1cSKars de Jong 23a16efc1cSKars de Jong MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>"); 24a16efc1cSKars de Jong MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver"); 25a16efc1cSKars de Jong MODULE_LICENSE("GPL"); 26a16efc1cSKars de Jong 27a16efc1cSKars de Jong 28a16efc1cSKars de Jong static struct scsi_host_template a4000t_scsi_driver_template = { 29a16efc1cSKars de Jong .name = "A4000T builtin SCSI", 30a16efc1cSKars de Jong .proc_name = "A4000t", 31a16efc1cSKars de Jong .this_id = 7, 32a16efc1cSKars de Jong .module = THIS_MODULE, 33a16efc1cSKars de Jong }; 34a16efc1cSKars de Jong 35a16efc1cSKars de Jong static struct platform_device *a4000t_scsi_device; 36a16efc1cSKars de Jong 37a16efc1cSKars de Jong #define A4000T_SCSI_ADDR 0xdd0040 38a16efc1cSKars de Jong 397a192ec3SMing Lei static int __devinit a4000t_probe(struct platform_device *dev) 40a16efc1cSKars de Jong { 41bbfbbbc1SMariusz Kozlowski struct Scsi_Host *host; 42a16efc1cSKars de Jong struct NCR_700_Host_Parameters *hostdata; 43a16efc1cSKars de Jong 44a16efc1cSKars de Jong if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI))) 45a16efc1cSKars de Jong goto out; 46a16efc1cSKars de Jong 47a16efc1cSKars de Jong if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000, 48a16efc1cSKars de Jong "A4000T builtin SCSI")) 49a16efc1cSKars de Jong goto out; 50a16efc1cSKars de Jong 51bbfbbbc1SMariusz Kozlowski hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); 52bbfbbbc1SMariusz Kozlowski if (!hostdata) { 53a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n"); 54a16efc1cSKars de Jong goto out_release; 55a16efc1cSKars de Jong } 56a16efc1cSKars de Jong 57a16efc1cSKars de Jong /* Fill in the required pieces of hostdata */ 58a16efc1cSKars de Jong hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR); 59a16efc1cSKars de Jong hostdata->clock = 50; 60a16efc1cSKars de Jong hostdata->chip710 = 1; 61a16efc1cSKars de Jong hostdata->dmode_extra = DMODE_FC2; 62a16efc1cSKars de Jong hostdata->dcntl_extra = EA_710; 63a16efc1cSKars de Jong 64a16efc1cSKars de Jong /* and register the chip */ 65e5779a58SGeert Uytterhoeven host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, 66e5779a58SGeert Uytterhoeven &dev->dev); 67a16efc1cSKars de Jong if (!host) { 68a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: No host detected; " 69a16efc1cSKars de Jong "board configuration problem?\n"); 70a16efc1cSKars de Jong goto out_free; 71a16efc1cSKars de Jong } 72a16efc1cSKars de Jong 73a16efc1cSKars de Jong host->this_id = 7; 74a16efc1cSKars de Jong host->base = A4000T_SCSI_ADDR; 75a16efc1cSKars de Jong host->irq = IRQ_AMIGA_PORTS; 76a16efc1cSKars de Jong 77a16efc1cSKars de Jong if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", 78a16efc1cSKars de Jong host)) { 79a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: request_irq failed\n"); 80a16efc1cSKars de Jong goto out_put_host; 81a16efc1cSKars de Jong } 82a16efc1cSKars de Jong 837a192ec3SMing Lei platform_set_drvdata(dev, host); 84a16efc1cSKars de Jong scsi_scan_host(host); 85a16efc1cSKars de Jong 86a16efc1cSKars de Jong return 0; 87a16efc1cSKars de Jong 88a16efc1cSKars de Jong out_put_host: 89a16efc1cSKars de Jong scsi_host_put(host); 90a16efc1cSKars de Jong out_free: 91a16efc1cSKars de Jong kfree(hostdata); 92a16efc1cSKars de Jong out_release: 93a16efc1cSKars de Jong release_mem_region(A4000T_SCSI_ADDR, 0x1000); 94a16efc1cSKars de Jong out: 95a16efc1cSKars de Jong return -ENODEV; 96a16efc1cSKars de Jong } 97a16efc1cSKars de Jong 987a192ec3SMing Lei static __devexit int a4000t_device_remove(struct platform_device *dev) 99a16efc1cSKars de Jong { 1007a192ec3SMing Lei struct Scsi_Host *host = platform_get_drvdata(dev); 101a16efc1cSKars de Jong struct NCR_700_Host_Parameters *hostdata = shost_priv(host); 102a16efc1cSKars de Jong 103a16efc1cSKars de Jong scsi_remove_host(host); 104a16efc1cSKars de Jong 105a16efc1cSKars de Jong NCR_700_release(host); 106a16efc1cSKars de Jong kfree(hostdata); 107a16efc1cSKars de Jong free_irq(host->irq, host); 108a16efc1cSKars de Jong release_mem_region(A4000T_SCSI_ADDR, 0x1000); 109a16efc1cSKars de Jong 110a16efc1cSKars de Jong return 0; 111a16efc1cSKars de Jong } 112a16efc1cSKars de Jong 1137a192ec3SMing Lei static struct platform_driver a4000t_scsi_driver = { 1147a192ec3SMing Lei .driver = { 115a16efc1cSKars de Jong .name = "a4000t-scsi", 1167a192ec3SMing Lei .owner = THIS_MODULE, 1177a192ec3SMing Lei }, 118a16efc1cSKars de Jong .probe = a4000t_probe, 119a16efc1cSKars de Jong .remove = __devexit_p(a4000t_device_remove), 120a16efc1cSKars de Jong }; 121a16efc1cSKars de Jong 122a16efc1cSKars de Jong static int __init a4000t_scsi_init(void) 123a16efc1cSKars de Jong { 124a16efc1cSKars de Jong int err; 125a16efc1cSKars de Jong 1267a192ec3SMing Lei err = platform_driver_register(&a4000t_scsi_driver); 127a16efc1cSKars de Jong if (err) 128a16efc1cSKars de Jong return err; 129a16efc1cSKars de Jong 130a16efc1cSKars de Jong a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", 131a16efc1cSKars de Jong -1, NULL, 0); 132a16efc1cSKars de Jong if (IS_ERR(a4000t_scsi_device)) { 1332d138ae0SGeert Uytterhoeven platform_driver_unregister(&a4000t_scsi_driver); 134a16efc1cSKars de Jong return PTR_ERR(a4000t_scsi_device); 135a16efc1cSKars de Jong } 136a16efc1cSKars de Jong 137a16efc1cSKars de Jong return err; 138a16efc1cSKars de Jong } 139a16efc1cSKars de Jong 140a16efc1cSKars de Jong static void __exit a4000t_scsi_exit(void) 141a16efc1cSKars de Jong { 142a16efc1cSKars de Jong platform_device_unregister(a4000t_scsi_device); 1437a192ec3SMing Lei platform_driver_unregister(&a4000t_scsi_driver); 144a16efc1cSKars de Jong } 145a16efc1cSKars de Jong 146a16efc1cSKars de Jong module_init(a4000t_scsi_init); 147a16efc1cSKars de Jong module_exit(a4000t_scsi_exit); 148