Merge branches 'gemini' and 'misc' into devel
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / scsi / a4000t.c
1 /*
2  * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
3  *              Amiga Technologies A4000T SCSI controller.
4  *
5  * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
6  * plus modifications of the 53c7xx.c driver to support the Amiga.
7  *
8  * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
9  */
10
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/init.h>
14 #include <linux/interrupt.h>
15 #include <linux/slab.h>
16 #include <asm/amigahw.h>
17 #include <asm/amigaints.h>
18 #include <scsi/scsi_host.h>
19 #include <scsi/scsi_transport_spi.h>
20
21 #include "53c700.h"
22
23
24 static struct scsi_host_template a4000t_scsi_driver_template = {
25         .name           = "A4000T builtin SCSI",
26         .proc_name      = "A4000t",
27         .this_id        = 7,
28         .module         = THIS_MODULE,
29 };
30
31
32 #define A4000T_SCSI_OFFSET      0x40
33
34 static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev)
35 {
36         struct resource *res;
37         phys_addr_t scsi_addr;
38         struct NCR_700_Host_Parameters *hostdata;
39         struct Scsi_Host *host;
40
41         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
42         if (!res)
43                 return -ENODEV;
44
45         if (!request_mem_region(res->start, resource_size(res),
46                                 "A4000T builtin SCSI"))
47                 return -EBUSY;
48
49         hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters),
50                            GFP_KERNEL);
51         if (!hostdata) {
52                 dev_err(&pdev->dev, "Failed to allocate host data\n");
53                 goto out_release;
54         }
55
56         scsi_addr = res->start + A4000T_SCSI_OFFSET;
57
58         /* Fill in the required pieces of hostdata */
59         hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr);
60         hostdata->clock = 50;
61         hostdata->chip710 = 1;
62         hostdata->dmode_extra = DMODE_FC2;
63         hostdata->dcntl_extra = EA_710;
64
65         /* and register the chip */
66         host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata,
67                               &pdev->dev);
68         if (!host) {
69                 dev_err(&pdev->dev,
70                         "No host detected; board configuration problem?\n");
71                 goto out_free;
72         }
73
74         host->this_id = 7;
75         host->base = scsi_addr;
76         host->irq = IRQ_AMIGA_PORTS;
77
78         if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi",
79                         host)) {
80                 dev_err(&pdev->dev, "request_irq failed\n");
81                 goto out_put_host;
82         }
83
84         platform_set_drvdata(pdev, host);
85         scsi_scan_host(host);
86         return 0;
87
88  out_put_host:
89         scsi_host_put(host);
90  out_free:
91         kfree(hostdata);
92  out_release:
93         release_mem_region(res->start, resource_size(res));
94         return -ENODEV;
95 }
96
97 static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev)
98 {
99         struct Scsi_Host *host = platform_get_drvdata(pdev);
100         struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
101         struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
102
103         scsi_remove_host(host);
104         NCR_700_release(host);
105         kfree(hostdata);
106         free_irq(host->irq, host);
107         release_mem_region(res->start, resource_size(res));
108         return 0;
109 }
110
111 static struct platform_driver amiga_a4000t_scsi_driver = {
112         .remove = __exit_p(amiga_a4000t_scsi_remove),
113         .driver   = {
114                 .name   = "amiga-a4000t-scsi",
115                 .owner  = THIS_MODULE,
116         },
117 };
118
119 static int __init amiga_a4000t_scsi_init(void)
120 {
121         return platform_driver_probe(&amiga_a4000t_scsi_driver,
122                                      amiga_a4000t_scsi_probe);
123 }
124
125 module_init(amiga_a4000t_scsi_init);
126
127 static void __exit amiga_a4000t_scsi_exit(void)
128 {
129         platform_driver_unregister(&amiga_a4000t_scsi_driver);
130 }
131
132 module_exit(amiga_a4000t_scsi_exit);
133
134 MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / "
135               "Kars de Jong <jongk@linux-m68k.org>");
136 MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
137 MODULE_LICENSE("GPL");
138 MODULE_ALIAS("platform:amiga-a4000t-scsi");