xref: /OK3568_Linux_fs/kernel/drivers/scsi/zalon.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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