1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Zalon 53c7xx device driver.
4*4882a593Smuzhiyun * By Richard Hirst (rhirst@linuxcare.com)
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/init.h>
8*4882a593Smuzhiyun #include <linux/interrupt.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/types.h>
11*4882a593Smuzhiyun #include <asm/hardware.h>
12*4882a593Smuzhiyun #include <asm/io.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include "../parisc/gsc.h"
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include "ncr53c8xx.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun MODULE_AUTHOR("Richard Hirst");
19*4882a593Smuzhiyun MODULE_DESCRIPTION("Bluefish/Zalon 720 SCSI Driver");
20*4882a593Smuzhiyun MODULE_LICENSE("GPL");
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define GSC_SCSI_ZALON_OFFSET 0x800
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define IO_MODULE_EIM (1*4)
25*4882a593Smuzhiyun #define IO_MODULE_DC_ADATA (2*4)
26*4882a593Smuzhiyun #define IO_MODULE_II_CDATA (3*4)
27*4882a593Smuzhiyun #define IO_MODULE_IO_COMMAND (12*4)
28*4882a593Smuzhiyun #define IO_MODULE_IO_STATUS (13*4)
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #define IOSTATUS_RY 0x40
31*4882a593Smuzhiyun #define IOSTATUS_FE 0x80
32*4882a593Smuzhiyun #define IOIIDATA_SMINT5L 0x40000000
33*4882a593Smuzhiyun #define IOIIDATA_MINT5EN 0x20000000
34*4882a593Smuzhiyun #define IOIIDATA_PACKEN 0x10000000
35*4882a593Smuzhiyun #define IOIIDATA_PREFETCHEN 0x08000000
36*4882a593Smuzhiyun #define IOIIDATA_IOII 0x00000020
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define CMD_RESET 5
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static struct ncr_chip zalon720_chip __initdata = {
41*4882a593Smuzhiyun .revision_id = 0x0f,
42*4882a593Smuzhiyun .burst_max = 3,
43*4882a593Smuzhiyun .offset_max = 8,
44*4882a593Smuzhiyun .nr_divisor = 4,
45*4882a593Smuzhiyun .features = FE_WIDE | FE_DIFF | FE_EHP| FE_MUX | FE_EA,
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #if 0
51*4882a593Smuzhiyun /* FIXME:
52*4882a593Smuzhiyun * Is this function dead code? or is someone planning on using it in the
53*4882a593Smuzhiyun * future. The clock = (int) pdc_result[16] does not look correct to
54*4882a593Smuzhiyun * me ... I think it should be iodc_data[16]. Since this cause a compile
55*4882a593Smuzhiyun * error with the new encapsulated PDC, I'm not compiling in this function.
56*4882a593Smuzhiyun * - RB
57*4882a593Smuzhiyun */
58*4882a593Smuzhiyun /* poke SCSI clock out of iodc data */
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun static u8 iodc_data[32] __attribute__ ((aligned (64)));
61*4882a593Smuzhiyun static unsigned long pdc_result[32] __attribute__ ((aligned (16))) ={0,0,0,0};
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static int
64*4882a593Smuzhiyun lasi_scsi_clock(void * hpa, int defaultclock)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun int clock, status;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun status = pdc_iodc_read(&pdc_result, hpa, 0, &iodc_data, 32 );
69*4882a593Smuzhiyun if (status == PDC_RET_OK) {
70*4882a593Smuzhiyun clock = (int) pdc_result[16];
71*4882a593Smuzhiyun } else {
72*4882a593Smuzhiyun printk(KERN_WARNING "%s: pdc_iodc_read returned %d\n", __func__, status);
73*4882a593Smuzhiyun clock = defaultclock;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun printk(KERN_DEBUG "%s: SCSI clock %d\n", __func__, clock);
77*4882a593Smuzhiyun return clock;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun #endif
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun static struct scsi_host_template zalon7xx_template = {
82*4882a593Smuzhiyun .module = THIS_MODULE,
83*4882a593Smuzhiyun .proc_name = "zalon7xx",
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun static int __init
zalon_probe(struct parisc_device * dev)87*4882a593Smuzhiyun zalon_probe(struct parisc_device *dev)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun struct gsc_irq gsc_irq;
90*4882a593Smuzhiyun u32 zalon_vers;
91*4882a593Smuzhiyun int error = -ENODEV;
92*4882a593Smuzhiyun void __iomem *zalon = ioremap(dev->hpa.start, 4096);
93*4882a593Smuzhiyun void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET;
94*4882a593Smuzhiyun static int unit = 0;
95*4882a593Smuzhiyun struct Scsi_Host *host;
96*4882a593Smuzhiyun struct ncr_device device;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun __raw_writel(CMD_RESET, zalon + IO_MODULE_IO_COMMAND);
99*4882a593Smuzhiyun while (!(__raw_readl(zalon + IO_MODULE_IO_STATUS) & IOSTATUS_RY))
100*4882a593Smuzhiyun cpu_relax();
101*4882a593Smuzhiyun __raw_writel(IOIIDATA_MINT5EN | IOIIDATA_PACKEN | IOIIDATA_PREFETCHEN,
102*4882a593Smuzhiyun zalon + IO_MODULE_II_CDATA);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /* XXX: Save the Zalon version for bug workarounds? */
105*4882a593Smuzhiyun zalon_vers = (__raw_readl(zalon + IO_MODULE_II_CDATA) >> 24) & 0x07;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* Setup the interrupts first.
108*4882a593Smuzhiyun ** Later on request_irq() will register the handler.
109*4882a593Smuzhiyun */
110*4882a593Smuzhiyun dev->irq = gsc_alloc_irq(&gsc_irq);
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun printk(KERN_INFO "%s: Zalon version %d, IRQ %d\n", __func__,
113*4882a593Smuzhiyun zalon_vers, dev->irq);
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun __raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, zalon + IO_MODULE_EIM);
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun if (zalon_vers == 0)
118*4882a593Smuzhiyun printk(KERN_WARNING "%s: Zalon 1.1 or earlier\n", __func__);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun memset(&device, 0, sizeof(struct ncr_device));
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /* The following three are needed before any other access. */
123*4882a593Smuzhiyun __raw_writeb(0x20, io_port + 0x38); /* DCNTL_REG, EA */
124*4882a593Smuzhiyun __raw_writeb(0x04, io_port + 0x1b); /* CTEST0_REG, EHP */
125*4882a593Smuzhiyun __raw_writeb(0x80, io_port + 0x22); /* CTEST4_REG, MUX */
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /* Initialise ncr_device structure with items required by ncr_attach. */
128*4882a593Smuzhiyun device.chip = zalon720_chip;
129*4882a593Smuzhiyun device.host_id = 7;
130*4882a593Smuzhiyun device.dev = &dev->dev;
131*4882a593Smuzhiyun device.slot.base = dev->hpa.start + GSC_SCSI_ZALON_OFFSET;
132*4882a593Smuzhiyun device.slot.base_v = io_port;
133*4882a593Smuzhiyun device.slot.irq = dev->irq;
134*4882a593Smuzhiyun device.differential = 2;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun host = ncr_attach(&zalon7xx_template, unit, &device);
137*4882a593Smuzhiyun if (!host)
138*4882a593Smuzhiyun return -ENODEV;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) {
141*4882a593Smuzhiyun dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ",
142*4882a593Smuzhiyun dev->irq);
143*4882a593Smuzhiyun goto fail;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun unit++;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun dev_set_drvdata(&dev->dev, host);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun error = scsi_add_host(host, &dev->dev);
151*4882a593Smuzhiyun if (error)
152*4882a593Smuzhiyun goto fail_free_irq;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun scsi_scan_host(host);
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun fail_free_irq:
158*4882a593Smuzhiyun free_irq(dev->irq, host);
159*4882a593Smuzhiyun fail:
160*4882a593Smuzhiyun ncr53c8xx_release(host);
161*4882a593Smuzhiyun return error;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun static const struct parisc_device_id zalon_tbl[] __initconst = {
165*4882a593Smuzhiyun { HPHW_A_DMA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00089 },
166*4882a593Smuzhiyun { 0, }
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun MODULE_DEVICE_TABLE(parisc, zalon_tbl);
170*4882a593Smuzhiyun
zalon_remove(struct parisc_device * dev)171*4882a593Smuzhiyun static int __exit zalon_remove(struct parisc_device *dev)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun scsi_remove_host(host);
176*4882a593Smuzhiyun ncr53c8xx_release(host);
177*4882a593Smuzhiyun free_irq(dev->irq, host);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun return 0;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun static struct parisc_driver zalon_driver __refdata = {
183*4882a593Smuzhiyun .name = "zalon",
184*4882a593Smuzhiyun .id_table = zalon_tbl,
185*4882a593Smuzhiyun .probe = zalon_probe,
186*4882a593Smuzhiyun .remove = __exit_p(zalon_remove),
187*4882a593Smuzhiyun };
188*4882a593Smuzhiyun
zalon7xx_init(void)189*4882a593Smuzhiyun static int __init zalon7xx_init(void)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun int ret = ncr53c8xx_init();
192*4882a593Smuzhiyun if (!ret)
193*4882a593Smuzhiyun ret = register_parisc_driver(&zalon_driver);
194*4882a593Smuzhiyun if (ret)
195*4882a593Smuzhiyun ncr53c8xx_exit();
196*4882a593Smuzhiyun return ret;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
zalon7xx_exit(void)199*4882a593Smuzhiyun static void __exit zalon7xx_exit(void)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun unregister_parisc_driver(&zalon_driver);
202*4882a593Smuzhiyun ncr53c8xx_exit();
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun module_init(zalon7xx_init);
206*4882a593Smuzhiyun module_exit(zalon7xx_exit);
207