blob: ea0c572c75046848e23f2c932a5271e8b64699c0 [file] [log] [blame]
David S. Millercd9ad582007-04-26 21:19:23 -07001/* sun_esp.c: ESP front-end for Sparc SBUS systems.
2 *
David S. Miller334ae612008-08-27 17:01:57 -07003 * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net)
David S. Millercd9ad582007-04-26 21:19:23 -07004 */
5
6#include <linux/kernel.h>
7#include <linux/types.h>
David S. Miller6025dfe2007-04-29 16:12:29 -07008#include <linux/delay.h>
David S. Millercd9ad582007-04-26 21:19:23 -07009#include <linux/module.h>
Andrea Righi27ac7922008-07-23 21:28:13 -070010#include <linux/mm.h>
David S. Millercd9ad582007-04-26 21:19:23 -070011#include <linux/init.h>
David S. Miller738f2b72008-08-27 18:09:11 -070012#include <linux/dma-mapping.h>
David S. Millercd9ad582007-04-26 21:19:23 -070013
14#include <asm/irq.h>
15#include <asm/io.h>
16#include <asm/dma.h>
17
18#include <asm/sbus.h>
19
20#include <scsi/scsi_host.h>
21
22#include "esp_scsi.h"
23
24#define DRV_MODULE_NAME "sun_esp"
25#define PFX DRV_MODULE_NAME ": "
26#define DRV_VERSION "1.000"
27#define DRV_MODULE_RELDATE "April 19, 2007"
28
29#define dma_read32(REG) \
30 sbus_readl(esp->dma_regs + (REG))
31#define dma_write32(VAL, REG) \
32 sbus_writel((VAL), esp->dma_regs + (REG))
33
David S. Miller334ae612008-08-27 17:01:57 -070034/* DVMA chip revisions */
35enum dvma_rev {
36 dvmarev0,
37 dvmaesc1,
38 dvmarev1,
39 dvmarev2,
40 dvmarev3,
41 dvmarevplus,
42 dvmahme
43};
44
45static int __devinit esp_sbus_setup_dma(struct esp *esp,
46 struct of_device *dma_of)
David S. Millercd9ad582007-04-26 21:19:23 -070047{
David S. Miller334ae612008-08-27 17:01:57 -070048 esp->dma = dma_of;
David S. Millercd9ad582007-04-26 21:19:23 -070049
David S. Miller334ae612008-08-27 17:01:57 -070050 esp->dma_regs = of_ioremap(&dma_of->resource[0], 0,
51 resource_size(&dma_of->resource[0]),
52 "espdma");
53 if (!esp->dma_regs)
54 return -ENOMEM;
David S. Millercd9ad582007-04-26 21:19:23 -070055
David S. Miller334ae612008-08-27 17:01:57 -070056 switch (dma_read32(DMA_CSR) & DMA_DEVICE_ID) {
57 case DMA_VERS0:
58 esp->dmarev = dvmarev0;
59 break;
60 case DMA_ESCV1:
61 esp->dmarev = dvmaesc1;
62 break;
63 case DMA_VERS1:
64 esp->dmarev = dvmarev1;
65 break;
66 case DMA_VERS2:
67 esp->dmarev = dvmarev2;
68 break;
69 case DMA_VERHME:
70 esp->dmarev = dvmahme;
71 break;
72 case DMA_VERSPLUS:
73 esp->dmarev = dvmarevplus;
74 break;
David S. Millercd9ad582007-04-26 21:19:23 -070075 }
76
David S. Millercd9ad582007-04-26 21:19:23 -070077 return 0;
78
79}
80
81static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
82{
83 struct sbus_dev *sdev = esp->dev;
84 struct resource *res;
85
86 /* On HME, two reg sets exist, first is DVMA,
87 * second is ESP registers.
88 */
89 if (hme)
90 res = &sdev->resource[1];
91 else
92 res = &sdev->resource[0];
93
94 esp->regs = sbus_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP");
95 if (!esp->regs)
96 return -ENOMEM;
97
98 return 0;
99}
100
101static int __devinit esp_sbus_map_command_block(struct esp *esp)
102{
103 struct sbus_dev *sdev = esp->dev;
104
David S. Miller738f2b72008-08-27 18:09:11 -0700105 esp->command_block = dma_alloc_coherent(&sdev->ofdev.dev, 16,
106 &esp->command_block_dma,
107 GFP_ATOMIC);
David S. Millercd9ad582007-04-26 21:19:23 -0700108 if (!esp->command_block)
109 return -ENOMEM;
110 return 0;
111}
112
113static int __devinit esp_sbus_register_irq(struct esp *esp)
114{
115 struct Scsi_Host *host = esp->host;
116 struct sbus_dev *sdev = esp->dev;
117
118 host->irq = sdev->irqs[0];
119 return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
120}
121
122static void __devinit esp_get_scsi_id(struct esp *esp)
123{
124 struct sbus_dev *sdev = esp->dev;
125 struct device_node *dp = sdev->ofdev.node;
126
127 esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff);
128 if (esp->scsi_id != 0xff)
129 goto done;
130
131 esp->scsi_id = of_getintprop_default(dp, "scsi-initiator-id", 0xff);
132 if (esp->scsi_id != 0xff)
133 goto done;
134
135 if (!sdev->bus) {
136 /* SUN4 */
137 esp->scsi_id = 7;
138 goto done;
139 }
140
141 esp->scsi_id = of_getintprop_default(sdev->bus->ofdev.node,
142 "scsi-initiator-id", 7);
143
144done:
145 esp->host->this_id = esp->scsi_id;
146 esp->scsi_id_mask = (1 << esp->scsi_id);
147}
148
149static void __devinit esp_get_differential(struct esp *esp)
150{
151 struct sbus_dev *sdev = esp->dev;
152 struct device_node *dp = sdev->ofdev.node;
153
154 if (of_find_property(dp, "differential", NULL))
155 esp->flags |= ESP_FLAG_DIFFERENTIAL;
156 else
157 esp->flags &= ~ESP_FLAG_DIFFERENTIAL;
158}
159
160static void __devinit esp_get_clock_params(struct esp *esp)
161{
162 struct sbus_dev *sdev = esp->dev;
163 struct device_node *dp = sdev->ofdev.node;
164 struct device_node *bus_dp;
165 int fmhz;
166
167 bus_dp = NULL;
168 if (sdev != NULL && sdev->bus != NULL)
169 bus_dp = sdev->bus->ofdev.node;
170
171 fmhz = of_getintprop_default(dp, "clock-frequency", 0);
172 if (fmhz == 0)
173 fmhz = (!bus_dp) ? 0 :
174 of_getintprop_default(bus_dp, "clock-frequency", 0);
175
176 esp->cfreq = fmhz;
177}
178
David S. Miller334ae612008-08-27 17:01:57 -0700179static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of)
David S. Millercd9ad582007-04-26 21:19:23 -0700180{
David S. Miller334ae612008-08-27 17:01:57 -0700181 struct device_node *dma_dp = dma_of->node;
David S. Millercd9ad582007-04-26 21:19:23 -0700182 struct sbus_dev *sdev = esp->dev;
David S. Miller334ae612008-08-27 17:01:57 -0700183 struct device_node *dp;
184 u8 bursts, val;
David S. Millercd9ad582007-04-26 21:19:23 -0700185
David S. Miller334ae612008-08-27 17:01:57 -0700186 dp = sdev->ofdev.node;
David S. Millercd9ad582007-04-26 21:19:23 -0700187 bursts = of_getintprop_default(dp, "burst-sizes", 0xff);
David S. Miller334ae612008-08-27 17:01:57 -0700188 val = of_getintprop_default(dma_dp, "burst-sizes", 0xff);
189 if (val != 0xff)
190 bursts &= val;
David S. Millercd9ad582007-04-26 21:19:23 -0700191
192 if (sdev->bus) {
193 u8 val = of_getintprop_default(sdev->bus->ofdev.node,
194 "burst-sizes", 0xff);
195 if (val != 0xff)
196 bursts &= val;
197 }
198
199 if (bursts == 0xff ||
200 (bursts & DMA_BURST16) == 0 ||
201 (bursts & DMA_BURST32) == 0)
202 bursts = (DMA_BURST32 - 1);
203
204 esp->bursts = bursts;
205}
206
David S. Miller334ae612008-08-27 17:01:57 -0700207static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma)
David S. Millercd9ad582007-04-26 21:19:23 -0700208{
209 esp_get_scsi_id(esp);
210 esp_get_differential(esp);
211 esp_get_clock_params(esp);
212 esp_get_bursts(esp, espdma);
213}
214
215static void sbus_esp_write8(struct esp *esp, u8 val, unsigned long reg)
216{
217 sbus_writeb(val, esp->regs + (reg * 4UL));
218}
219
220static u8 sbus_esp_read8(struct esp *esp, unsigned long reg)
221{
222 return sbus_readb(esp->regs + (reg * 4UL));
223}
224
225static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf,
226 size_t sz, int dir)
227{
David S. Miller7a715f42008-08-27 18:37:58 -0700228 struct sbus_dev *sdev = esp->dev;
229
David S. Miller738f2b72008-08-27 18:09:11 -0700230 return dma_map_single(&sdev->ofdev.dev, buf, sz, dir);
David S. Millercd9ad582007-04-26 21:19:23 -0700231}
232
233static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg,
234 int num_sg, int dir)
235{
David S. Miller7a715f42008-08-27 18:37:58 -0700236 struct sbus_dev *sdev = esp->dev;
237
David S. Miller738f2b72008-08-27 18:09:11 -0700238 return dma_map_sg(&sdev->ofdev.dev, sg, num_sg, dir);
David S. Millercd9ad582007-04-26 21:19:23 -0700239}
240
241static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr,
242 size_t sz, int dir)
243{
David S. Miller7a715f42008-08-27 18:37:58 -0700244 struct sbus_dev *sdev = esp->dev;
245
David S. Miller738f2b72008-08-27 18:09:11 -0700246 dma_unmap_single(&sdev->ofdev.dev, addr, sz, dir);
David S. Millercd9ad582007-04-26 21:19:23 -0700247}
248
249static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
250 int num_sg, int dir)
251{
David S. Miller7a715f42008-08-27 18:37:58 -0700252 struct sbus_dev *sdev = esp->dev;
253
David S. Miller738f2b72008-08-27 18:09:11 -0700254 dma_unmap_sg(&sdev->ofdev.dev, sg, num_sg, dir);
David S. Millercd9ad582007-04-26 21:19:23 -0700255}
256
257static int sbus_esp_irq_pending(struct esp *esp)
258{
259 if (dma_read32(DMA_CSR) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
260 return 1;
261 return 0;
262}
263
264static void sbus_esp_reset_dma(struct esp *esp)
265{
266 int can_do_burst16, can_do_burst32, can_do_burst64;
267 int can_do_sbus64, lim;
David S. Miller63237ee2008-08-26 23:33:42 -0700268 struct sbus_dev *sdev;
David S. Millercd9ad582007-04-26 21:19:23 -0700269 u32 val;
270
271 can_do_burst16 = (esp->bursts & DMA_BURST16) != 0;
272 can_do_burst32 = (esp->bursts & DMA_BURST32) != 0;
273 can_do_burst64 = 0;
274 can_do_sbus64 = 0;
David S. Miller63237ee2008-08-26 23:33:42 -0700275 sdev = esp->dev;
276 if (sbus_can_dma_64bit())
David S. Millercd9ad582007-04-26 21:19:23 -0700277 can_do_sbus64 = 1;
David S. Miller63237ee2008-08-26 23:33:42 -0700278 if (sbus_can_burst64())
David S. Millercd9ad582007-04-26 21:19:23 -0700279 can_do_burst64 = (esp->bursts & DMA_BURST64) != 0;
280
281 /* Put the DVMA into a known state. */
David S. Miller334ae612008-08-27 17:01:57 -0700282 if (esp->dmarev != dvmahme) {
David S. Millercd9ad582007-04-26 21:19:23 -0700283 val = dma_read32(DMA_CSR);
284 dma_write32(val | DMA_RST_SCSI, DMA_CSR);
285 dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
286 }
David S. Miller334ae612008-08-27 17:01:57 -0700287 switch (esp->dmarev) {
David S. Millercd9ad582007-04-26 21:19:23 -0700288 case dvmahme:
289 dma_write32(DMA_RESET_FAS366, DMA_CSR);
290 dma_write32(DMA_RST_SCSI, DMA_CSR);
291
292 esp->prev_hme_dmacsr = (DMA_PARITY_OFF | DMA_2CLKS |
293 DMA_SCSI_DISAB | DMA_INT_ENAB);
294
295 esp->prev_hme_dmacsr &= ~(DMA_ENABLE | DMA_ST_WRITE |
296 DMA_BRST_SZ);
297
298 if (can_do_burst64)
299 esp->prev_hme_dmacsr |= DMA_BRST64;
300 else if (can_do_burst32)
301 esp->prev_hme_dmacsr |= DMA_BRST32;
302
303 if (can_do_sbus64) {
304 esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64;
David S. Miller63237ee2008-08-26 23:33:42 -0700305 sbus_set_sbus64(&sdev->ofdev.dev, esp->bursts);
David S. Millercd9ad582007-04-26 21:19:23 -0700306 }
307
308 lim = 1000;
309 while (dma_read32(DMA_CSR) & DMA_PEND_READ) {
310 if (--lim == 0) {
311 printk(KERN_ALERT PFX "esp%d: DMA_PEND_READ "
312 "will not clear!\n",
313 esp->host->unique_id);
314 break;
315 }
316 udelay(1);
317 }
318
319 dma_write32(0, DMA_CSR);
320 dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
321
322 dma_write32(0, DMA_ADDR);
323 break;
324
325 case dvmarev2:
326 if (esp->rev != ESP100) {
327 val = dma_read32(DMA_CSR);
328 dma_write32(val | DMA_3CLKS, DMA_CSR);
329 }
330 break;
331
332 case dvmarev3:
333 val = dma_read32(DMA_CSR);
334 val &= ~DMA_3CLKS;
335 val |= DMA_2CLKS;
336 if (can_do_burst32) {
337 val &= ~DMA_BRST_SZ;
338 val |= DMA_BRST32;
339 }
340 dma_write32(val, DMA_CSR);
341 break;
342
343 case dvmaesc1:
344 val = dma_read32(DMA_CSR);
345 val |= DMA_ADD_ENABLE;
346 val &= ~DMA_BCNT_ENAB;
347 if (!can_do_burst32 && can_do_burst16) {
348 val |= DMA_ESC_BURST;
349 } else {
350 val &= ~(DMA_ESC_BURST);
351 }
352 dma_write32(val, DMA_CSR);
353 break;
354
355 default:
356 break;
357 }
358
359 /* Enable interrupts. */
360 val = dma_read32(DMA_CSR);
361 dma_write32(val | DMA_INT_ENAB, DMA_CSR);
362}
363
364static void sbus_esp_dma_drain(struct esp *esp)
365{
366 u32 csr;
367 int lim;
368
David S. Miller334ae612008-08-27 17:01:57 -0700369 if (esp->dmarev == dvmahme)
David S. Millercd9ad582007-04-26 21:19:23 -0700370 return;
371
372 csr = dma_read32(DMA_CSR);
373 if (!(csr & DMA_FIFO_ISDRAIN))
374 return;
375
David S. Miller334ae612008-08-27 17:01:57 -0700376 if (esp->dmarev != dvmarev3 && esp->dmarev != dvmaesc1)
David S. Millercd9ad582007-04-26 21:19:23 -0700377 dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR);
378
379 lim = 1000;
380 while (dma_read32(DMA_CSR) & DMA_FIFO_ISDRAIN) {
381 if (--lim == 0) {
382 printk(KERN_ALERT PFX "esp%d: DMA will not drain!\n",
383 esp->host->unique_id);
384 break;
385 }
386 udelay(1);
387 }
388}
389
390static void sbus_esp_dma_invalidate(struct esp *esp)
391{
David S. Miller334ae612008-08-27 17:01:57 -0700392 if (esp->dmarev == dvmahme) {
David S. Millercd9ad582007-04-26 21:19:23 -0700393 dma_write32(DMA_RST_SCSI, DMA_CSR);
394
395 esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
396 (DMA_PARITY_OFF | DMA_2CLKS |
397 DMA_SCSI_DISAB | DMA_INT_ENAB)) &
398 ~(DMA_ST_WRITE | DMA_ENABLE));
399
400 dma_write32(0, DMA_CSR);
401 dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
402
403 /* This is necessary to avoid having the SCSI channel
404 * engine lock up on us.
405 */
406 dma_write32(0, DMA_ADDR);
407 } else {
408 u32 val;
409 int lim;
410
411 lim = 1000;
412 while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) {
413 if (--lim == 0) {
414 printk(KERN_ALERT PFX "esp%d: DMA will not "
415 "invalidate!\n", esp->host->unique_id);
416 break;
417 }
418 udelay(1);
419 }
420
421 val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB);
422 val |= DMA_FIFO_INV;
423 dma_write32(val, DMA_CSR);
424 val &= ~DMA_FIFO_INV;
425 dma_write32(val, DMA_CSR);
426 }
427}
428
429static void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
430 u32 dma_count, int write, u8 cmd)
431{
432 u32 csr;
433
434 BUG_ON(!(cmd & ESP_CMD_DMA));
435
436 sbus_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
437 sbus_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
438 if (esp->rev == FASHME) {
439 sbus_esp_write8(esp, (esp_count >> 16) & 0xff, FAS_RLO);
440 sbus_esp_write8(esp, 0, FAS_RHI);
441
442 scsi_esp_cmd(esp, cmd);
443
444 csr = esp->prev_hme_dmacsr;
445 csr |= DMA_SCSI_DISAB | DMA_ENABLE;
446 if (write)
447 csr |= DMA_ST_WRITE;
448 else
449 csr &= ~DMA_ST_WRITE;
450 esp->prev_hme_dmacsr = csr;
451
452 dma_write32(dma_count, DMA_COUNT);
453 dma_write32(addr, DMA_ADDR);
454 dma_write32(csr, DMA_CSR);
455 } else {
456 csr = dma_read32(DMA_CSR);
457 csr |= DMA_ENABLE;
458 if (write)
459 csr |= DMA_ST_WRITE;
460 else
461 csr &= ~DMA_ST_WRITE;
462 dma_write32(csr, DMA_CSR);
David S. Miller334ae612008-08-27 17:01:57 -0700463 if (esp->dmarev == dvmaesc1) {
David S. Millercd9ad582007-04-26 21:19:23 -0700464 u32 end = PAGE_ALIGN(addr + dma_count + 16U);
465 dma_write32(end - addr, DMA_COUNT);
466 }
467 dma_write32(addr, DMA_ADDR);
468
469 scsi_esp_cmd(esp, cmd);
470 }
471
472}
473
474static int sbus_esp_dma_error(struct esp *esp)
475{
476 u32 csr = dma_read32(DMA_CSR);
477
478 if (csr & DMA_HNDL_ERROR)
479 return 1;
480
481 return 0;
482}
483
484static const struct esp_driver_ops sbus_esp_ops = {
485 .esp_write8 = sbus_esp_write8,
486 .esp_read8 = sbus_esp_read8,
487 .map_single = sbus_esp_map_single,
488 .map_sg = sbus_esp_map_sg,
489 .unmap_single = sbus_esp_unmap_single,
490 .unmap_sg = sbus_esp_unmap_sg,
491 .irq_pending = sbus_esp_irq_pending,
492 .reset_dma = sbus_esp_reset_dma,
493 .dma_drain = sbus_esp_dma_drain,
494 .dma_invalidate = sbus_esp_dma_invalidate,
495 .send_dma_cmd = sbus_esp_send_dma_cmd,
496 .dma_error = sbus_esp_dma_error,
497};
498
499static int __devinit esp_sbus_probe_one(struct device *dev,
500 struct sbus_dev *esp_dev,
David S. Miller334ae612008-08-27 17:01:57 -0700501 struct of_device *espdma,
David S. Millercd9ad582007-04-26 21:19:23 -0700502 struct sbus_bus *sbus,
503 int hme)
504{
505 struct scsi_host_template *tpnt = &scsi_esp_template;
506 struct Scsi_Host *host;
507 struct esp *esp;
508 int err;
509
510 host = scsi_host_alloc(tpnt, sizeof(struct esp));
511
512 err = -ENOMEM;
513 if (!host)
514 goto fail;
515
516 host->max_id = (hme ? 16 : 8);
Christoph Hellwig2b14ec72007-05-31 20:12:32 +0200517 esp = shost_priv(host);
David S. Millercd9ad582007-04-26 21:19:23 -0700518
519 esp->host = host;
520 esp->dev = esp_dev;
521 esp->ops = &sbus_esp_ops;
522
523 if (hme)
524 esp->flags |= ESP_FLAG_WIDE_CAPABLE;
525
David S. Miller334ae612008-08-27 17:01:57 -0700526 err = esp_sbus_setup_dma(esp, espdma);
David S. Millercd9ad582007-04-26 21:19:23 -0700527 if (err < 0)
528 goto fail_unlink;
529
530 err = esp_sbus_map_regs(esp, hme);
531 if (err < 0)
532 goto fail_unlink;
533
534 err = esp_sbus_map_command_block(esp);
535 if (err < 0)
536 goto fail_unmap_regs;
537
538 err = esp_sbus_register_irq(esp);
539 if (err < 0)
540 goto fail_unmap_command_block;
541
542 esp_sbus_get_props(esp, espdma);
543
544 /* Before we try to touch the ESP chip, ESC1 dma can
545 * come up with the reset bit set, so make sure that
546 * is clear first.
547 */
David S. Miller334ae612008-08-27 17:01:57 -0700548 if (esp->dmarev == dvmaesc1) {
David S. Millercd9ad582007-04-26 21:19:23 -0700549 u32 val = dma_read32(DMA_CSR);
550
551 dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
552 }
553
554 dev_set_drvdata(&esp_dev->ofdev.dev, esp);
555
556 err = scsi_esp_register(esp, dev);
557 if (err)
558 goto fail_free_irq;
559
560 return 0;
561
562fail_free_irq:
563 free_irq(host->irq, esp);
564fail_unmap_command_block:
David S. Miller738f2b72008-08-27 18:09:11 -0700565 dma_free_coherent(&esp_dev->ofdev.dev, 16,
566 esp->command_block,
567 esp->command_block_dma);
David S. Millercd9ad582007-04-26 21:19:23 -0700568fail_unmap_regs:
569 sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE);
570fail_unlink:
571 scsi_host_put(host);
572fail:
573 return err;
574}
575
576static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match)
577{
578 struct sbus_dev *sdev = to_sbus_device(&dev->dev);
David S. Miller334ae612008-08-27 17:01:57 -0700579 struct device_node *dma_node = NULL;
David S. Millercd9ad582007-04-26 21:19:23 -0700580 struct device_node *dp = dev->node;
David S. Miller334ae612008-08-27 17:01:57 -0700581 struct of_device *dma_of = NULL;
David S. Millercd9ad582007-04-26 21:19:23 -0700582 int hme = 0;
583
584 if (dp->parent &&
585 (!strcmp(dp->parent->name, "espdma") ||
586 !strcmp(dp->parent->name, "dma")))
David S. Miller334ae612008-08-27 17:01:57 -0700587 dma_node = dp->parent;
David S. Millercd9ad582007-04-26 21:19:23 -0700588 else if (!strcmp(dp->name, "SUNW,fas")) {
David S. Miller334ae612008-08-27 17:01:57 -0700589 dma_node = sdev->ofdev.node;
David S. Millercd9ad582007-04-26 21:19:23 -0700590 hme = 1;
591 }
David S. Miller334ae612008-08-27 17:01:57 -0700592 if (dma_node)
593 dma_of = of_find_device_by_node(dma_node);
594 if (!dma_of)
595 return -ENODEV;
David S. Millercd9ad582007-04-26 21:19:23 -0700596
David S. Miller334ae612008-08-27 17:01:57 -0700597 return esp_sbus_probe_one(&dev->dev, sdev, dma_of,
David S. Millercd9ad582007-04-26 21:19:23 -0700598 sdev->bus, hme);
599}
600
601static int __devexit esp_sbus_remove(struct of_device *dev)
602{
603 struct esp *esp = dev_get_drvdata(&dev->dev);
David S. Miller7a715f42008-08-27 18:37:58 -0700604 struct sbus_dev *sdev = esp->dev;
David S. Miller334ae612008-08-27 17:01:57 -0700605 struct of_device *dma_of = esp->dma;
David S. Millercd9ad582007-04-26 21:19:23 -0700606 unsigned int irq = esp->host->irq;
607 u32 val;
608
609 scsi_esp_unregister(esp);
610
611 /* Disable interrupts. */
612 val = dma_read32(DMA_CSR);
613 dma_write32(val & ~DMA_INT_ENAB, DMA_CSR);
614
615 free_irq(irq, esp);
David S. Miller738f2b72008-08-27 18:09:11 -0700616 dma_free_coherent(&sdev->ofdev.dev, 16,
617 esp->command_block,
618 esp->command_block_dma);
David S. Millercd9ad582007-04-26 21:19:23 -0700619 sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE);
David S. Miller334ae612008-08-27 17:01:57 -0700620 of_iounmap(&dma_of->resource[0], esp->dma_regs,
621 resource_size(&dma_of->resource[0]));
David S. Millercd9ad582007-04-26 21:19:23 -0700622
623 scsi_host_put(esp->host);
624
625 return 0;
626}
627
628static struct of_device_id esp_match[] = {
629 {
630 .name = "SUNW,esp",
631 },
632 {
633 .name = "SUNW,fas",
634 },
635 {
636 .name = "esp",
637 },
638 {},
639};
640MODULE_DEVICE_TABLE(of, esp_match);
641
642static struct of_platform_driver esp_sbus_driver = {
643 .name = "esp",
644 .match_table = esp_match,
645 .probe = esp_sbus_probe,
646 .remove = __devexit_p(esp_sbus_remove),
647};
648
649static int __init sunesp_init(void)
650{
651 return of_register_driver(&esp_sbus_driver, &sbus_bus_type);
652}
653
654static void __exit sunesp_exit(void)
655{
656 of_unregister_driver(&esp_sbus_driver);
657}
658
659MODULE_DESCRIPTION("Sun ESP SCSI driver");
660MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
661MODULE_LICENSE("GPL");
662MODULE_VERSION(DRV_VERSION);
663
664module_init(sunesp_init);
665module_exit(sunesp_exit);