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> 1596249cf9SGeert Uytterhoeven #include <asm/amigahw.h> 16a16efc1cSKars de Jong #include <asm/amigaints.h> 17a16efc1cSKars de Jong #include <scsi/scsi_host.h> 18a16efc1cSKars de Jong #include <scsi/scsi_transport_spi.h> 19a16efc1cSKars de Jong 20a16efc1cSKars de Jong #include "53c700.h" 21a16efc1cSKars de Jong 22a16efc1cSKars de Jong MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>"); 23a16efc1cSKars de Jong MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver"); 24a16efc1cSKars de Jong MODULE_LICENSE("GPL"); 25a16efc1cSKars de Jong 26a16efc1cSKars de Jong 27a16efc1cSKars de Jong static struct scsi_host_template a4000t_scsi_driver_template = { 28a16efc1cSKars de Jong .name = "A4000T builtin SCSI", 29a16efc1cSKars de Jong .proc_name = "A4000t", 30a16efc1cSKars de Jong .this_id = 7, 31a16efc1cSKars de Jong .module = THIS_MODULE, 32a16efc1cSKars de Jong }; 33a16efc1cSKars de Jong 34a16efc1cSKars de Jong static struct platform_device *a4000t_scsi_device; 35a16efc1cSKars de Jong 36a16efc1cSKars de Jong #define A4000T_SCSI_ADDR 0xdd0040 37a16efc1cSKars de Jong 387a192ec3SMing Lei static int __devinit a4000t_probe(struct platform_device *dev) 39a16efc1cSKars de Jong { 40bbfbbbc1SMariusz Kozlowski struct Scsi_Host *host; 41a16efc1cSKars de Jong struct NCR_700_Host_Parameters *hostdata; 42a16efc1cSKars de Jong 43a16efc1cSKars de Jong if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI))) 44a16efc1cSKars de Jong goto out; 45a16efc1cSKars de Jong 46a16efc1cSKars de Jong if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000, 47a16efc1cSKars de Jong "A4000T builtin SCSI")) 48a16efc1cSKars de Jong goto out; 49a16efc1cSKars de Jong 50bbfbbbc1SMariusz Kozlowski hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); 51bbfbbbc1SMariusz Kozlowski if (!hostdata) { 52a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n"); 53a16efc1cSKars de Jong goto out_release; 54a16efc1cSKars de Jong } 55a16efc1cSKars de Jong 56a16efc1cSKars de Jong /* Fill in the required pieces of hostdata */ 57a16efc1cSKars de Jong hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR); 58a16efc1cSKars de Jong hostdata->clock = 50; 59a16efc1cSKars de Jong hostdata->chip710 = 1; 60a16efc1cSKars de Jong hostdata->dmode_extra = DMODE_FC2; 61a16efc1cSKars de Jong hostdata->dcntl_extra = EA_710; 62a16efc1cSKars de Jong 63a16efc1cSKars de Jong /* and register the chip */ 64*e5779a58SGeert Uytterhoeven host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, 65*e5779a58SGeert Uytterhoeven &dev->dev); 66a16efc1cSKars de Jong if (!host) { 67a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: No host detected; " 68a16efc1cSKars de Jong "board configuration problem?\n"); 69a16efc1cSKars de Jong goto out_free; 70a16efc1cSKars de Jong } 71a16efc1cSKars de Jong 72a16efc1cSKars de Jong host->this_id = 7; 73a16efc1cSKars de Jong host->base = A4000T_SCSI_ADDR; 74a16efc1cSKars de Jong host->irq = IRQ_AMIGA_PORTS; 75a16efc1cSKars de Jong 76a16efc1cSKars de Jong if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", 77a16efc1cSKars de Jong host)) { 78a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: request_irq failed\n"); 79a16efc1cSKars de Jong goto out_put_host; 80a16efc1cSKars de Jong } 81a16efc1cSKars de Jong 827a192ec3SMing Lei platform_set_drvdata(dev, host); 83a16efc1cSKars de Jong scsi_scan_host(host); 84a16efc1cSKars de Jong 85a16efc1cSKars de Jong return 0; 86a16efc1cSKars de Jong 87a16efc1cSKars de Jong out_put_host: 88a16efc1cSKars de Jong scsi_host_put(host); 89a16efc1cSKars de Jong out_free: 90a16efc1cSKars de Jong kfree(hostdata); 91a16efc1cSKars de Jong out_release: 92a16efc1cSKars de Jong release_mem_region(A4000T_SCSI_ADDR, 0x1000); 93a16efc1cSKars de Jong out: 94a16efc1cSKars de Jong return -ENODEV; 95a16efc1cSKars de Jong } 96a16efc1cSKars de Jong 977a192ec3SMing Lei static __devexit int a4000t_device_remove(struct platform_device *dev) 98a16efc1cSKars de Jong { 997a192ec3SMing Lei struct Scsi_Host *host = platform_get_drvdata(dev); 100a16efc1cSKars de Jong struct NCR_700_Host_Parameters *hostdata = shost_priv(host); 101a16efc1cSKars de Jong 102a16efc1cSKars de Jong scsi_remove_host(host); 103a16efc1cSKars de Jong 104a16efc1cSKars de Jong NCR_700_release(host); 105a16efc1cSKars de Jong kfree(hostdata); 106a16efc1cSKars de Jong free_irq(host->irq, host); 107a16efc1cSKars de Jong release_mem_region(A4000T_SCSI_ADDR, 0x1000); 108a16efc1cSKars de Jong 109a16efc1cSKars de Jong return 0; 110a16efc1cSKars de Jong } 111a16efc1cSKars de Jong 1127a192ec3SMing Lei static struct platform_driver a4000t_scsi_driver = { 1137a192ec3SMing Lei .driver = { 114a16efc1cSKars de Jong .name = "a4000t-scsi", 1157a192ec3SMing Lei .owner = THIS_MODULE, 1167a192ec3SMing Lei }, 117a16efc1cSKars de Jong .probe = a4000t_probe, 118a16efc1cSKars de Jong .remove = __devexit_p(a4000t_device_remove), 119a16efc1cSKars de Jong }; 120a16efc1cSKars de Jong 121a16efc1cSKars de Jong static int __init a4000t_scsi_init(void) 122a16efc1cSKars de Jong { 123a16efc1cSKars de Jong int err; 124a16efc1cSKars de Jong 1257a192ec3SMing Lei err = platform_driver_register(&a4000t_scsi_driver); 126a16efc1cSKars de Jong if (err) 127a16efc1cSKars de Jong return err; 128a16efc1cSKars de Jong 129a16efc1cSKars de Jong a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", 130a16efc1cSKars de Jong -1, NULL, 0); 131a16efc1cSKars de Jong if (IS_ERR(a4000t_scsi_device)) { 1327a192ec3SMing Lei platform_driver_register(&a4000t_scsi_driver); 133a16efc1cSKars de Jong return PTR_ERR(a4000t_scsi_device); 134a16efc1cSKars de Jong } 135a16efc1cSKars de Jong 136a16efc1cSKars de Jong return err; 137a16efc1cSKars de Jong } 138a16efc1cSKars de Jong 139a16efc1cSKars de Jong static void __exit a4000t_scsi_exit(void) 140a16efc1cSKars de Jong { 141a16efc1cSKars de Jong platform_device_unregister(a4000t_scsi_device); 1427a192ec3SMing Lei platform_driver_unregister(&a4000t_scsi_driver); 143a16efc1cSKars de Jong } 144a16efc1cSKars de Jong 145a16efc1cSKars de Jong module_init(a4000t_scsi_init); 146a16efc1cSKars de Jong module_exit(a4000t_scsi_exit); 147