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