Blame view

drivers/scsi/sun_esp.c 14.2 KB
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
1
2
  /* sun_esp.c: ESP front-end for Sparc SBUS systems.
   *
334ae6147   David S. Miller   sparc: Kill SBUS ...
3
   * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net)
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
4
5
6
7
   */
  
  #include <linux/kernel.h>
  #include <linux/types.h>
6025dfe5b   David S. Miller   [SCSI] SUNESP: su...
8
  #include <linux/delay.h>
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
9
  #include <linux/module.h>
27ac792ca   Andrea Righi   PAGE_ALIGN(): cor...
10
  #include <linux/mm.h>
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
11
  #include <linux/init.h>
738f2b7b8   David S. Miller   sparc: Convert al...
12
  #include <linux/dma-mapping.h>
05bb5e93f   David S. Miller   sun_esp: Convert ...
13
14
  #include <linux/of.h>
  #include <linux/of_device.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/gfp.h>
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
16
17
18
19
  
  #include <asm/irq.h>
  #include <asm/io.h>
  #include <asm/dma.h>
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
20
21
22
23
24
25
  #include <scsi/scsi_host.h>
  
  #include "esp_scsi.h"
  
  #define DRV_MODULE_NAME		"sun_esp"
  #define PFX DRV_MODULE_NAME	": "
05bb5e93f   David S. Miller   sun_esp: Convert ...
26
27
  #define DRV_VERSION		"1.100"
  #define DRV_MODULE_RELDATE	"August 27, 2008"
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
28
29
30
31
32
  
  #define dma_read32(REG) \
  	sbus_readl(esp->dma_regs + (REG))
  #define dma_write32(VAL, REG) \
  	sbus_writel((VAL), esp->dma_regs + (REG))
334ae6147   David S. Miller   sparc: Kill SBUS ...
33
34
35
36
37
38
39
40
41
42
  /* DVMA chip revisions */
  enum dvma_rev {
  	dvmarev0,
  	dvmaesc1,
  	dvmarev1,
  	dvmarev2,
  	dvmarev3,
  	dvmarevplus,
  	dvmahme
  };
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
43

334ae6147   David S. Miller   sparc: Kill SBUS ...
44
  static int __devinit esp_sbus_setup_dma(struct esp *esp,
2dc115813   Grant Likely   of/device: Replac...
45
  					struct platform_device *dma_of)
334ae6147   David S. Miller   sparc: Kill SBUS ...
46
47
  {
  	esp->dma = dma_of;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
48

334ae6147   David S. Miller   sparc: Kill SBUS ...
49
50
51
52
53
  	esp->dma_regs = of_ioremap(&dma_of->resource[0], 0,
  				   resource_size(&dma_of->resource[0]),
  				   "espdma");
  	if (!esp->dma_regs)
  		return -ENOMEM;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
54

334ae6147   David S. Miller   sparc: Kill SBUS ...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  	switch (dma_read32(DMA_CSR) & DMA_DEVICE_ID) {
  	case DMA_VERS0:
  		esp->dmarev = dvmarev0;
  		break;
  	case DMA_ESCV1:
  		esp->dmarev = dvmaesc1;
  		break;
  	case DMA_VERS1:
  		esp->dmarev = dvmarev1;
  		break;
  	case DMA_VERS2:
  		esp->dmarev = dvmarev2;
  		break;
  	case DMA_VERHME:
  		esp->dmarev = dvmahme;
  		break;
  	case DMA_VERSPLUS:
  		esp->dmarev = dvmarevplus;
  		break;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
74
  	}
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
75
76
77
78
79
80
81
  
  	return 0;
  
  }
  
  static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
  {
2dc115813   Grant Likely   of/device: Replac...
82
  	struct platform_device *op = esp->dev;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
83
84
85
86
87
88
  	struct resource *res;
  
  	/* On HME, two reg sets exist, first is DVMA,
  	 * second is ESP registers.
  	 */
  	if (hme)
05bb5e93f   David S. Miller   sun_esp: Convert ...
89
  		res = &op->resource[1];
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
90
  	else
05bb5e93f   David S. Miller   sun_esp: Convert ...
91
  		res = &op->resource[0];
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
92

05bb5e93f   David S. Miller   sun_esp: Convert ...
93
  	esp->regs = of_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP");
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
94
95
96
97
98
99
100
101
  	if (!esp->regs)
  		return -ENOMEM;
  
  	return 0;
  }
  
  static int __devinit esp_sbus_map_command_block(struct esp *esp)
  {
2dc115813   Grant Likely   of/device: Replac...
102
  	struct platform_device *op = esp->dev;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
103

05bb5e93f   David S. Miller   sun_esp: Convert ...
104
  	esp->command_block = dma_alloc_coherent(&op->dev, 16,
738f2b7b8   David S. Miller   sparc: Convert al...
105
106
  						&esp->command_block_dma,
  						GFP_ATOMIC);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
107
108
109
110
111
112
113
114
  	if (!esp->command_block)
  		return -ENOMEM;
  	return 0;
  }
  
  static int __devinit esp_sbus_register_irq(struct esp *esp)
  {
  	struct Scsi_Host *host = esp->host;
2dc115813   Grant Likely   of/device: Replac...
115
  	struct platform_device *op = esp->dev;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
116

1636f8ac2   Grant Likely   sparc/of: Move of...
117
  	host->irq = op->archdata.irqs[0];
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
118
119
  	return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
  }
2dc115813   Grant Likely   of/device: Replac...
120
  static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma)
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
121
  {
2dc115813   Grant Likely   of/device: Replac...
122
  	struct platform_device *op = esp->dev;
05bb5e93f   David S. Miller   sun_esp: Convert ...
123
  	struct device_node *dp;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
124

61c7a080a   Grant Likely   of: Always use 's...
125
  	dp = op->dev.of_node;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
126
127
128
129
130
131
132
  	esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff);
  	if (esp->scsi_id != 0xff)
  		goto done;
  
  	esp->scsi_id = of_getintprop_default(dp, "scsi-initiator-id", 0xff);
  	if (esp->scsi_id != 0xff)
  		goto done;
61c7a080a   Grant Likely   of: Always use 's...
133
  	esp->scsi_id = of_getintprop_default(espdma->dev.of_node,
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
134
135
136
137
138
139
140
141
142
  					     "scsi-initiator-id", 7);
  
  done:
  	esp->host->this_id = esp->scsi_id;
  	esp->scsi_id_mask = (1 << esp->scsi_id);
  }
  
  static void __devinit esp_get_differential(struct esp *esp)
  {
2dc115813   Grant Likely   of/device: Replac...
143
  	struct platform_device *op = esp->dev;
05bb5e93f   David S. Miller   sun_esp: Convert ...
144
  	struct device_node *dp;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
145

61c7a080a   Grant Likely   of: Always use 's...
146
  	dp = op->dev.of_node;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
147
148
149
150
151
152
153
154
  	if (of_find_property(dp, "differential", NULL))
  		esp->flags |= ESP_FLAG_DIFFERENTIAL;
  	else
  		esp->flags &= ~ESP_FLAG_DIFFERENTIAL;
  }
  
  static void __devinit esp_get_clock_params(struct esp *esp)
  {
2dc115813   Grant Likely   of/device: Replac...
155
  	struct platform_device *op = esp->dev;
05bb5e93f   David S. Miller   sun_esp: Convert ...
156
  	struct device_node *bus_dp, *dp;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
157
  	int fmhz;
61c7a080a   Grant Likely   of: Always use 's...
158
  	dp = op->dev.of_node;
05bb5e93f   David S. Miller   sun_esp: Convert ...
159
  	bus_dp = dp->parent;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
160
161
162
  
  	fmhz = of_getintprop_default(dp, "clock-frequency", 0);
  	if (fmhz == 0)
05bb5e93f   David S. Miller   sun_esp: Convert ...
163
  		fmhz = of_getintprop_default(bus_dp, "clock-frequency", 0);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
164
165
166
  
  	esp->cfreq = fmhz;
  }
2dc115813   Grant Likely   of/device: Replac...
167
  static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of)
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
168
  {
61c7a080a   Grant Likely   of: Always use 's...
169
  	struct device_node *dma_dp = dma_of->dev.of_node;
2dc115813   Grant Likely   of/device: Replac...
170
  	struct platform_device *op = esp->dev;
334ae6147   David S. Miller   sparc: Kill SBUS ...
171
172
  	struct device_node *dp;
  	u8 bursts, val;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
173

61c7a080a   Grant Likely   of: Always use 's...
174
  	dp = op->dev.of_node;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
175
  	bursts = of_getintprop_default(dp, "burst-sizes", 0xff);
334ae6147   David S. Miller   sparc: Kill SBUS ...
176
177
178
  	val = of_getintprop_default(dma_dp, "burst-sizes", 0xff);
  	if (val != 0xff)
  		bursts &= val;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
179

05bb5e93f   David S. Miller   sun_esp: Convert ...
180
181
182
  	val = of_getintprop_default(dma_dp->parent, "burst-sizes", 0xff);
  	if (val != 0xff)
  		bursts &= val;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
183
184
185
186
187
188
189
190
  
  	if (bursts == 0xff ||
  	    (bursts & DMA_BURST16) == 0 ||
  	    (bursts & DMA_BURST32) == 0)
  		bursts = (DMA_BURST32 - 1);
  
  	esp->bursts = bursts;
  }
2dc115813   Grant Likely   of/device: Replac...
191
  static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma)
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
192
  {
05bb5e93f   David S. Miller   sun_esp: Convert ...
193
  	esp_get_scsi_id(esp, espdma);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  	esp_get_differential(esp);
  	esp_get_clock_params(esp);
  	esp_get_bursts(esp, espdma);
  }
  
  static void sbus_esp_write8(struct esp *esp, u8 val, unsigned long reg)
  {
  	sbus_writeb(val, esp->regs + (reg * 4UL));
  }
  
  static u8 sbus_esp_read8(struct esp *esp, unsigned long reg)
  {
  	return sbus_readb(esp->regs + (reg * 4UL));
  }
  
  static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf,
  				      size_t sz, int dir)
  {
2dc115813   Grant Likely   of/device: Replac...
212
  	struct platform_device *op = esp->dev;
7a715f460   David S. Miller   sparc: Make SBUS ...
213

05bb5e93f   David S. Miller   sun_esp: Convert ...
214
  	return dma_map_single(&op->dev, buf, sz, dir);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
215
216
217
218
219
  }
  
  static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg,
  				  int num_sg, int dir)
  {
2dc115813   Grant Likely   of/device: Replac...
220
  	struct platform_device *op = esp->dev;
7a715f460   David S. Miller   sparc: Make SBUS ...
221

05bb5e93f   David S. Miller   sun_esp: Convert ...
222
  	return dma_map_sg(&op->dev, sg, num_sg, dir);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
223
224
225
226
227
  }
  
  static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr,
  				  size_t sz, int dir)
  {
2dc115813   Grant Likely   of/device: Replac...
228
  	struct platform_device *op = esp->dev;
7a715f460   David S. Miller   sparc: Make SBUS ...
229

05bb5e93f   David S. Miller   sun_esp: Convert ...
230
  	dma_unmap_single(&op->dev, addr, sz, dir);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
231
232
233
234
235
  }
  
  static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
  			      int num_sg, int dir)
  {
2dc115813   Grant Likely   of/device: Replac...
236
  	struct platform_device *op = esp->dev;
7a715f460   David S. Miller   sparc: Make SBUS ...
237

05bb5e93f   David S. Miller   sun_esp: Convert ...
238
  	dma_unmap_sg(&op->dev, sg, num_sg, dir);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
239
240
241
242
243
244
245
246
247
248
249
250
251
  }
  
  static int sbus_esp_irq_pending(struct esp *esp)
  {
  	if (dma_read32(DMA_CSR) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
  		return 1;
  	return 0;
  }
  
  static void sbus_esp_reset_dma(struct esp *esp)
  {
  	int can_do_burst16, can_do_burst32, can_do_burst64;
  	int can_do_sbus64, lim;
2dc115813   Grant Likely   of/device: Replac...
252
  	struct platform_device *op;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
253
254
255
256
257
258
  	u32 val;
  
  	can_do_burst16 = (esp->bursts & DMA_BURST16) != 0;
  	can_do_burst32 = (esp->bursts & DMA_BURST32) != 0;
  	can_do_burst64 = 0;
  	can_do_sbus64 = 0;
05bb5e93f   David S. Miller   sun_esp: Convert ...
259
  	op = esp->dev;
63237eeb5   David S. Miller   sparc: Move SBUS ...
260
  	if (sbus_can_dma_64bit())
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
261
  		can_do_sbus64 = 1;
63237eeb5   David S. Miller   sparc: Move SBUS ...
262
  	if (sbus_can_burst64())
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
263
264
265
  		can_do_burst64 = (esp->bursts & DMA_BURST64) != 0;
  
  	/* Put the DVMA into a known state. */
334ae6147   David S. Miller   sparc: Kill SBUS ...
266
  	if (esp->dmarev != dvmahme) {
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
267
268
269
270
  		val = dma_read32(DMA_CSR);
  		dma_write32(val | DMA_RST_SCSI, DMA_CSR);
  		dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
  	}
334ae6147   David S. Miller   sparc: Kill SBUS ...
271
  	switch (esp->dmarev) {
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  	case dvmahme:
  		dma_write32(DMA_RESET_FAS366, DMA_CSR);
  		dma_write32(DMA_RST_SCSI, DMA_CSR);
  
  		esp->prev_hme_dmacsr = (DMA_PARITY_OFF | DMA_2CLKS |
  					DMA_SCSI_DISAB | DMA_INT_ENAB);
  
  		esp->prev_hme_dmacsr &= ~(DMA_ENABLE | DMA_ST_WRITE |
  					  DMA_BRST_SZ);
  
  		if (can_do_burst64)
  			esp->prev_hme_dmacsr |= DMA_BRST64;
  		else if (can_do_burst32)
  			esp->prev_hme_dmacsr |= DMA_BRST32;
  
  		if (can_do_sbus64) {
  			esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64;
05bb5e93f   David S. Miller   sun_esp: Convert ...
289
  			sbus_set_sbus64(&op->dev, esp->bursts);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
  		}
  
  		lim = 1000;
  		while (dma_read32(DMA_CSR) & DMA_PEND_READ) {
  			if (--lim == 0) {
  				printk(KERN_ALERT PFX "esp%d: DMA_PEND_READ "
  				       "will not clear!
  ",
  				       esp->host->unique_id);
  				break;
  			}
  			udelay(1);
  		}
  
  		dma_write32(0, DMA_CSR);
  		dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
  
  		dma_write32(0, DMA_ADDR);
  		break;
  
  	case dvmarev2:
  		if (esp->rev != ESP100) {
  			val = dma_read32(DMA_CSR);
  			dma_write32(val | DMA_3CLKS, DMA_CSR);
  		}
  		break;
  
  	case dvmarev3:
  		val = dma_read32(DMA_CSR);
  		val &= ~DMA_3CLKS;
  		val |= DMA_2CLKS;
  		if (can_do_burst32) {
  			val &= ~DMA_BRST_SZ;
  			val |= DMA_BRST32;
  		}
  		dma_write32(val, DMA_CSR);
  		break;
  
  	case dvmaesc1:
  		val = dma_read32(DMA_CSR);
  		val |= DMA_ADD_ENABLE;
  		val &= ~DMA_BCNT_ENAB;
  		if (!can_do_burst32 && can_do_burst16) {
  			val |= DMA_ESC_BURST;
  		} else {
  			val &= ~(DMA_ESC_BURST);
  		}
  		dma_write32(val, DMA_CSR);
  		break;
  
  	default:
  		break;
  	}
  
  	/* Enable interrupts.  */
  	val = dma_read32(DMA_CSR);
  	dma_write32(val | DMA_INT_ENAB, DMA_CSR);
  }
  
  static void sbus_esp_dma_drain(struct esp *esp)
  {
  	u32 csr;
  	int lim;
334ae6147   David S. Miller   sparc: Kill SBUS ...
353
  	if (esp->dmarev == dvmahme)
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
354
355
356
357
358
  		return;
  
  	csr = dma_read32(DMA_CSR);
  	if (!(csr & DMA_FIFO_ISDRAIN))
  		return;
334ae6147   David S. Miller   sparc: Kill SBUS ...
359
  	if (esp->dmarev != dvmarev3 && esp->dmarev != dvmaesc1)
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  		dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR);
  
  	lim = 1000;
  	while (dma_read32(DMA_CSR) & DMA_FIFO_ISDRAIN) {
  		if (--lim == 0) {
  			printk(KERN_ALERT PFX "esp%d: DMA will not drain!
  ",
  			       esp->host->unique_id);
  			break;
  		}
  		udelay(1);
  	}
  }
  
  static void sbus_esp_dma_invalidate(struct esp *esp)
  {
334ae6147   David S. Miller   sparc: Kill SBUS ...
376
  	if (esp->dmarev == dvmahme) {
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
  		dma_write32(DMA_RST_SCSI, DMA_CSR);
  
  		esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
  					 (DMA_PARITY_OFF | DMA_2CLKS |
  					  DMA_SCSI_DISAB | DMA_INT_ENAB)) &
  					~(DMA_ST_WRITE | DMA_ENABLE));
  
  		dma_write32(0, DMA_CSR);
  		dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
  
  		/* This is necessary to avoid having the SCSI channel
  		 * engine lock up on us.
  		 */
  		dma_write32(0, DMA_ADDR);
  	} else {
  		u32 val;
  		int lim;
  
  		lim = 1000;
  		while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) {
  			if (--lim == 0) {
  				printk(KERN_ALERT PFX "esp%d: DMA will not "
  				       "invalidate!
  ", esp->host->unique_id);
  				break;
  			}
  			udelay(1);
  		}
  
  		val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB);
  		val |= DMA_FIFO_INV;
  		dma_write32(val, DMA_CSR);
  		val &= ~DMA_FIFO_INV;
  		dma_write32(val, DMA_CSR);
  	}
  }
  
  static void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
  				  u32 dma_count, int write, u8 cmd)
  {
  	u32 csr;
  
  	BUG_ON(!(cmd & ESP_CMD_DMA));
  
  	sbus_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
  	sbus_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
  	if (esp->rev == FASHME) {
  		sbus_esp_write8(esp, (esp_count >> 16) & 0xff, FAS_RLO);
  		sbus_esp_write8(esp, 0, FAS_RHI);
  
  		scsi_esp_cmd(esp, cmd);
  
  		csr = esp->prev_hme_dmacsr;
  		csr |= DMA_SCSI_DISAB | DMA_ENABLE;
  		if (write)
  			csr |= DMA_ST_WRITE;
  		else
  			csr &= ~DMA_ST_WRITE;
  		esp->prev_hme_dmacsr = csr;
  
  		dma_write32(dma_count, DMA_COUNT);
  		dma_write32(addr, DMA_ADDR);
  		dma_write32(csr, DMA_CSR);
  	} else {
  		csr = dma_read32(DMA_CSR);
  		csr |= DMA_ENABLE;
  		if (write)
  			csr |= DMA_ST_WRITE;
  		else
  			csr &= ~DMA_ST_WRITE;
  		dma_write32(csr, DMA_CSR);
334ae6147   David S. Miller   sparc: Kill SBUS ...
448
  		if (esp->dmarev == dvmaesc1) {
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  			u32 end = PAGE_ALIGN(addr + dma_count + 16U);
  			dma_write32(end - addr, DMA_COUNT);
  		}
  		dma_write32(addr, DMA_ADDR);
  
  		scsi_esp_cmd(esp, cmd);
  	}
  
  }
  
  static int sbus_esp_dma_error(struct esp *esp)
  {
  	u32 csr = dma_read32(DMA_CSR);
  
  	if (csr & DMA_HNDL_ERROR)
  		return 1;
  
  	return 0;
  }
  
  static const struct esp_driver_ops sbus_esp_ops = {
  	.esp_write8	=	sbus_esp_write8,
  	.esp_read8	=	sbus_esp_read8,
  	.map_single	=	sbus_esp_map_single,
  	.map_sg		=	sbus_esp_map_sg,
  	.unmap_single	=	sbus_esp_unmap_single,
  	.unmap_sg	=	sbus_esp_unmap_sg,
  	.irq_pending	=	sbus_esp_irq_pending,
  	.reset_dma	=	sbus_esp_reset_dma,
  	.dma_drain	=	sbus_esp_dma_drain,
  	.dma_invalidate	=	sbus_esp_dma_invalidate,
  	.send_dma_cmd	=	sbus_esp_send_dma_cmd,
  	.dma_error	=	sbus_esp_dma_error,
  };
2dc115813   Grant Likely   of/device: Replac...
483
484
  static int __devinit esp_sbus_probe_one(struct platform_device *op,
  					struct platform_device *espdma,
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
  					int hme)
  {
  	struct scsi_host_template *tpnt = &scsi_esp_template;
  	struct Scsi_Host *host;
  	struct esp *esp;
  	int err;
  
  	host = scsi_host_alloc(tpnt, sizeof(struct esp));
  
  	err = -ENOMEM;
  	if (!host)
  		goto fail;
  
  	host->max_id = (hme ? 16 : 8);
2b14ec787   Christoph Hellwig   [SCSI] esp: use s...
499
  	esp = shost_priv(host);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
500
501
  
  	esp->host = host;
05bb5e93f   David S. Miller   sun_esp: Convert ...
502
  	esp->dev = op;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
503
504
505
506
  	esp->ops = &sbus_esp_ops;
  
  	if (hme)
  		esp->flags |= ESP_FLAG_WIDE_CAPABLE;
334ae6147   David S. Miller   sparc: Kill SBUS ...
507
  	err = esp_sbus_setup_dma(esp, espdma);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
  	if (err < 0)
  		goto fail_unlink;
  
  	err = esp_sbus_map_regs(esp, hme);
  	if (err < 0)
  		goto fail_unlink;
  
  	err = esp_sbus_map_command_block(esp);
  	if (err < 0)
  		goto fail_unmap_regs;
  
  	err = esp_sbus_register_irq(esp);
  	if (err < 0)
  		goto fail_unmap_command_block;
  
  	esp_sbus_get_props(esp, espdma);
  
  	/* Before we try to touch the ESP chip, ESC1 dma can
  	 * come up with the reset bit set, so make sure that
  	 * is clear first.
  	 */
334ae6147   David S. Miller   sparc: Kill SBUS ...
529
  	if (esp->dmarev == dvmaesc1) {
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
530
531
532
533
  		u32 val = dma_read32(DMA_CSR);
  
  		dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
  	}
05bb5e93f   David S. Miller   sun_esp: Convert ...
534
  	dev_set_drvdata(&op->dev, esp);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
535

05bb5e93f   David S. Miller   sun_esp: Convert ...
536
  	err = scsi_esp_register(esp, &op->dev);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
537
538
539
540
541
542
543
544
  	if (err)
  		goto fail_free_irq;
  
  	return 0;
  
  fail_free_irq:
  	free_irq(host->irq, esp);
  fail_unmap_command_block:
05bb5e93f   David S. Miller   sun_esp: Convert ...
545
  	dma_free_coherent(&op->dev, 16,
738f2b7b8   David S. Miller   sparc: Convert al...
546
547
  			  esp->command_block,
  			  esp->command_block_dma);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
548
  fail_unmap_regs:
05bb5e93f   David S. Miller   sun_esp: Convert ...
549
  	of_iounmap(&op->resource[(hme ? 1 : 0)], esp->regs, SBUS_ESP_REG_SIZE);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
550
551
552
553
554
  fail_unlink:
  	scsi_host_put(host);
  fail:
  	return err;
  }
4ebb24f70   Grant Likely   dt/sparc: Elimina...
555
  static int __devinit esp_sbus_probe(struct platform_device *op)
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
556
  {
334ae6147   David S. Miller   sparc: Kill SBUS ...
557
  	struct device_node *dma_node = NULL;
61c7a080a   Grant Likely   of: Always use 's...
558
  	struct device_node *dp = op->dev.of_node;
2dc115813   Grant Likely   of/device: Replac...
559
  	struct platform_device *dma_of = NULL;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
560
561
562
563
564
  	int hme = 0;
  
  	if (dp->parent &&
  	    (!strcmp(dp->parent->name, "espdma") ||
  	     !strcmp(dp->parent->name, "dma")))
334ae6147   David S. Miller   sparc: Kill SBUS ...
565
  		dma_node = dp->parent;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
566
  	else if (!strcmp(dp->name, "SUNW,fas")) {
61c7a080a   Grant Likely   of: Always use 's...
567
  		dma_node = op->dev.of_node;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
568
569
  		hme = 1;
  	}
334ae6147   David S. Miller   sparc: Kill SBUS ...
570
571
572
573
  	if (dma_node)
  		dma_of = of_find_device_by_node(dma_node);
  	if (!dma_of)
  		return -ENODEV;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
574

05bb5e93f   David S. Miller   sun_esp: Convert ...
575
  	return esp_sbus_probe_one(op, dma_of, hme);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
576
  }
2dc115813   Grant Likely   of/device: Replac...
577
  static int __devexit esp_sbus_remove(struct platform_device *op)
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
578
  {
05bb5e93f   David S. Miller   sun_esp: Convert ...
579
  	struct esp *esp = dev_get_drvdata(&op->dev);
2dc115813   Grant Likely   of/device: Replac...
580
  	struct platform_device *dma_of = esp->dma;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
581
  	unsigned int irq = esp->host->irq;
05bb5e93f   David S. Miller   sun_esp: Convert ...
582
  	bool is_hme;
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
583
584
585
586
587
588
589
590
591
  	u32 val;
  
  	scsi_esp_unregister(esp);
  
  	/* Disable interrupts.  */
  	val = dma_read32(DMA_CSR);
  	dma_write32(val & ~DMA_INT_ENAB, DMA_CSR);
  
  	free_irq(irq, esp);
05bb5e93f   David S. Miller   sun_esp: Convert ...
592
593
594
595
  
  	is_hme = (esp->dmarev == dvmahme);
  
  	dma_free_coherent(&op->dev, 16,
738f2b7b8   David S. Miller   sparc: Convert al...
596
597
  			  esp->command_block,
  			  esp->command_block_dma);
05bb5e93f   David S. Miller   sun_esp: Convert ...
598
599
  	of_iounmap(&op->resource[(is_hme ? 1 : 0)], esp->regs,
  		   SBUS_ESP_REG_SIZE);
334ae6147   David S. Miller   sparc: Kill SBUS ...
600
601
  	of_iounmap(&dma_of->resource[0], esp->dma_regs,
  		   resource_size(&dma_of->resource[0]));
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
602
603
  
  	scsi_host_put(esp->host);
05bb5e93f   David S. Miller   sun_esp: Convert ...
604
  	dev_set_drvdata(&op->dev, NULL);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
605
606
  	return 0;
  }
fd098316e   David S. Miller   sparc: Annotate o...
607
  static const struct of_device_id esp_match[] = {
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
608
609
610
611
612
613
614
615
616
617
618
619
  	{
  		.name = "SUNW,esp",
  	},
  	{
  		.name = "SUNW,fas",
  	},
  	{
  		.name = "esp",
  	},
  	{},
  };
  MODULE_DEVICE_TABLE(of, esp_match);
4ebb24f70   Grant Likely   dt/sparc: Elimina...
620
  static struct platform_driver esp_sbus_driver = {
4018294b5   Grant Likely   of: Remove duplic...
621
622
623
624
625
  	.driver = {
  		.name = "esp",
  		.owner = THIS_MODULE,
  		.of_match_table = esp_match,
  	},
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
626
627
628
629
630
631
  	.probe		= esp_sbus_probe,
  	.remove		= __devexit_p(esp_sbus_remove),
  };
  
  static int __init sunesp_init(void)
  {
4ebb24f70   Grant Likely   dt/sparc: Elimina...
632
  	return platform_driver_register(&esp_sbus_driver);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
633
634
635
636
  }
  
  static void __exit sunesp_exit(void)
  {
4ebb24f70   Grant Likely   dt/sparc: Elimina...
637
  	platform_driver_unregister(&esp_sbus_driver);
cd9ad58d4   David S. Miller   [SCSI] SUNESP: Co...
638
639
640
641
642
643
644
645
646
  }
  
  MODULE_DESCRIPTION("Sun ESP SCSI driver");
  MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);
  
  module_init(sunesp_init);
  module_exit(sunesp_exit);