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 38*7a192ec3SMing 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 */ 64a16efc1cSKars de Jong host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, dev); 65a16efc1cSKars de Jong if (!host) { 66a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: No host detected; " 67a16efc1cSKars de Jong "board configuration problem?\n"); 68a16efc1cSKars de Jong goto out_free; 69a16efc1cSKars de Jong } 70a16efc1cSKars de Jong 71a16efc1cSKars de Jong host->this_id = 7; 72a16efc1cSKars de Jong host->base = A4000T_SCSI_ADDR; 73a16efc1cSKars de Jong host->irq = IRQ_AMIGA_PORTS; 74a16efc1cSKars de Jong 75a16efc1cSKars de Jong if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", 76a16efc1cSKars de Jong host)) { 77a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: request_irq failed\n"); 78a16efc1cSKars de Jong goto out_put_host; 79a16efc1cSKars de Jong } 80a16efc1cSKars de Jong 81*7a192ec3SMing Lei platform_set_drvdata(dev, host); 82a16efc1cSKars de Jong scsi_scan_host(host); 83a16efc1cSKars de Jong 84a16efc1cSKars de Jong return 0; 85a16efc1cSKars de Jong 86a16efc1cSKars de Jong out_put_host: 87a16efc1cSKars de Jong scsi_host_put(host); 88a16efc1cSKars de Jong out_free: 89a16efc1cSKars de Jong kfree(hostdata); 90a16efc1cSKars de Jong out_release: 91a16efc1cSKars de Jong release_mem_region(A4000T_SCSI_ADDR, 0x1000); 92a16efc1cSKars de Jong out: 93a16efc1cSKars de Jong return -ENODEV; 94a16efc1cSKars de Jong } 95a16efc1cSKars de Jong 96*7a192ec3SMing Lei static __devexit int a4000t_device_remove(struct platform_device *dev) 97a16efc1cSKars de Jong { 98*7a192ec3SMing Lei struct Scsi_Host *host = platform_get_drvdata(dev); 99a16efc1cSKars de Jong struct NCR_700_Host_Parameters *hostdata = shost_priv(host); 100a16efc1cSKars de Jong 101a16efc1cSKars de Jong scsi_remove_host(host); 102a16efc1cSKars de Jong 103a16efc1cSKars de Jong NCR_700_release(host); 104a16efc1cSKars de Jong kfree(hostdata); 105a16efc1cSKars de Jong free_irq(host->irq, host); 106a16efc1cSKars de Jong release_mem_region(A4000T_SCSI_ADDR, 0x1000); 107a16efc1cSKars de Jong 108a16efc1cSKars de Jong return 0; 109a16efc1cSKars de Jong } 110a16efc1cSKars de Jong 111*7a192ec3SMing Lei static struct platform_driver a4000t_scsi_driver = { 112*7a192ec3SMing Lei .driver = { 113a16efc1cSKars de Jong .name = "a4000t-scsi", 114*7a192ec3SMing Lei .owner = THIS_MODULE, 115*7a192ec3SMing Lei }, 116a16efc1cSKars de Jong .probe = a4000t_probe, 117a16efc1cSKars de Jong .remove = __devexit_p(a4000t_device_remove), 118a16efc1cSKars de Jong }; 119a16efc1cSKars de Jong 120a16efc1cSKars de Jong static int __init a4000t_scsi_init(void) 121a16efc1cSKars de Jong { 122a16efc1cSKars de Jong int err; 123a16efc1cSKars de Jong 124*7a192ec3SMing Lei err = platform_driver_register(&a4000t_scsi_driver); 125a16efc1cSKars de Jong if (err) 126a16efc1cSKars de Jong return err; 127a16efc1cSKars de Jong 128a16efc1cSKars de Jong a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", 129a16efc1cSKars de Jong -1, NULL, 0); 130a16efc1cSKars de Jong if (IS_ERR(a4000t_scsi_device)) { 131*7a192ec3SMing Lei platform_driver_register(&a4000t_scsi_driver); 132a16efc1cSKars de Jong return PTR_ERR(a4000t_scsi_device); 133a16efc1cSKars de Jong } 134a16efc1cSKars de Jong 135a16efc1cSKars de Jong return err; 136a16efc1cSKars de Jong } 137a16efc1cSKars de Jong 138a16efc1cSKars de Jong static void __exit a4000t_scsi_exit(void) 139a16efc1cSKars de Jong { 140a16efc1cSKars de Jong platform_device_unregister(a4000t_scsi_device); 141*7a192ec3SMing Lei platform_driver_unregister(&a4000t_scsi_driver); 142a16efc1cSKars de Jong } 143a16efc1cSKars de Jong 144a16efc1cSKars de Jong module_init(a4000t_scsi_init); 145a16efc1cSKars de Jong module_exit(a4000t_scsi_exit); 146