diff options
Diffstat (limited to 'drivers/scsi/sun_esp.c')
-rw-r--r-- | drivers/scsi/sun_esp.c | 122 |
1 files changed, 69 insertions, 53 deletions
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index f9cf70151366..d110b94f111e 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* sun_esp.c: ESP front-end for Sparc SBUS systems. | 1 | /* sun_esp.c: ESP front-end for Sparc SBUS systems. |
2 | * | 2 | * |
3 | * Copyright (C) 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
@@ -30,39 +30,48 @@ | |||
30 | #define dma_write32(VAL, REG) \ | 30 | #define dma_write32(VAL, REG) \ |
31 | sbus_writel((VAL), esp->dma_regs + (REG)) | 31 | sbus_writel((VAL), esp->dma_regs + (REG)) |
32 | 32 | ||
33 | static int __devinit esp_sbus_find_dma(struct esp *esp, struct sbus_dev *dma_sdev) | 33 | /* DVMA chip revisions */ |
34 | { | 34 | enum dvma_rev { |
35 | struct sbus_dev *sdev = esp->dev; | 35 | dvmarev0, |
36 | struct sbus_dma *dma; | 36 | dvmaesc1, |
37 | dvmarev1, | ||
38 | dvmarev2, | ||
39 | dvmarev3, | ||
40 | dvmarevplus, | ||
41 | dvmahme | ||
42 | }; | ||
37 | 43 | ||
38 | if (dma_sdev != NULL) { | 44 | static int __devinit esp_sbus_setup_dma(struct esp *esp, |
39 | for_each_dvma(dma) { | 45 | struct of_device *dma_of) |
40 | if (dma->sdev == dma_sdev) | 46 | { |
41 | break; | 47 | esp->dma = dma_of; |
42 | } | ||
43 | } else { | ||
44 | for_each_dvma(dma) { | ||
45 | if (dma->sdev == NULL) | ||
46 | break; | ||
47 | 48 | ||
48 | /* If bus + slot are the same and it has the | 49 | esp->dma_regs = of_ioremap(&dma_of->resource[0], 0, |
49 | * correct OBP name, it's ours. | 50 | resource_size(&dma_of->resource[0]), |
50 | */ | 51 | "espdma"); |
51 | if (sdev->bus == dma->sdev->bus && | 52 | if (!esp->dma_regs) |
52 | sdev->slot == dma->sdev->slot && | 53 | return -ENOMEM; |
53 | (!strcmp(dma->sdev->prom_name, "dma") || | ||
54 | !strcmp(dma->sdev->prom_name, "espdma"))) | ||
55 | break; | ||
56 | } | ||
57 | } | ||
58 | 54 | ||
59 | if (dma == NULL) { | 55 | switch (dma_read32(DMA_CSR) & DMA_DEVICE_ID) { |
60 | printk(KERN_ERR PFX "[%s] Cannot find dma.\n", | 56 | case DMA_VERS0: |
61 | sdev->ofdev.node->full_name); | 57 | esp->dmarev = dvmarev0; |
62 | return -ENODEV; | 58 | break; |
59 | case DMA_ESCV1: | ||
60 | esp->dmarev = dvmaesc1; | ||
61 | break; | ||
62 | case DMA_VERS1: | ||
63 | esp->dmarev = dvmarev1; | ||
64 | break; | ||
65 | case DMA_VERS2: | ||
66 | esp->dmarev = dvmarev2; | ||
67 | break; | ||
68 | case DMA_VERHME: | ||
69 | esp->dmarev = dvmahme; | ||
70 | break; | ||
71 | case DMA_VERSPLUS: | ||
72 | esp->dmarev = dvmarevplus; | ||
73 | break; | ||
63 | } | 74 | } |
64 | esp->dma = dma; | ||
65 | esp->dma_regs = dma->regs; | ||
66 | 75 | ||
67 | return 0; | 76 | return 0; |
68 | 77 | ||
@@ -165,19 +174,18 @@ static void __devinit esp_get_clock_params(struct esp *esp) | |||
165 | esp->cfreq = fmhz; | 174 | esp->cfreq = fmhz; |
166 | } | 175 | } |
167 | 176 | ||
168 | static void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma) | 177 | static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) |
169 | { | 178 | { |
179 | struct device_node *dma_dp = dma_of->node; | ||
170 | struct sbus_dev *sdev = esp->dev; | 180 | struct sbus_dev *sdev = esp->dev; |
171 | struct device_node *dp = sdev->ofdev.node; | 181 | struct device_node *dp; |
172 | u8 bursts; | 182 | u8 bursts, val; |
173 | 183 | ||
184 | dp = sdev->ofdev.node; | ||
174 | bursts = of_getintprop_default(dp, "burst-sizes", 0xff); | 185 | bursts = of_getintprop_default(dp, "burst-sizes", 0xff); |
175 | if (dma) { | 186 | val = of_getintprop_default(dma_dp, "burst-sizes", 0xff); |
176 | struct device_node *dma_dp = dma->ofdev.node; | 187 | if (val != 0xff) |
177 | u8 val = of_getintprop_default(dma_dp, "burst-sizes", 0xff); | 188 | bursts &= val; |
178 | if (val != 0xff) | ||
179 | bursts &= val; | ||
180 | } | ||
181 | 189 | ||
182 | if (sdev->bus) { | 190 | if (sdev->bus) { |
183 | u8 val = of_getintprop_default(sdev->bus->ofdev.node, | 191 | u8 val = of_getintprop_default(sdev->bus->ofdev.node, |
@@ -194,7 +202,7 @@ static void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma) | |||
194 | esp->bursts = bursts; | 202 | esp->bursts = bursts; |
195 | } | 203 | } |
196 | 204 | ||
197 | static void __devinit esp_sbus_get_props(struct esp *esp, struct sbus_dev *espdma) | 205 | static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma) |
198 | { | 206 | { |
199 | esp_get_scsi_id(esp); | 207 | esp_get_scsi_id(esp); |
200 | esp_get_differential(esp); | 208 | esp_get_differential(esp); |
@@ -259,12 +267,12 @@ static void sbus_esp_reset_dma(struct esp *esp) | |||
259 | can_do_burst64 = (esp->bursts & DMA_BURST64) != 0; | 267 | can_do_burst64 = (esp->bursts & DMA_BURST64) != 0; |
260 | 268 | ||
261 | /* Put the DVMA into a known state. */ | 269 | /* Put the DVMA into a known state. */ |
262 | if (esp->dma->revision != dvmahme) { | 270 | if (esp->dmarev != dvmahme) { |
263 | val = dma_read32(DMA_CSR); | 271 | val = dma_read32(DMA_CSR); |
264 | dma_write32(val | DMA_RST_SCSI, DMA_CSR); | 272 | dma_write32(val | DMA_RST_SCSI, DMA_CSR); |
265 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); | 273 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); |
266 | } | 274 | } |
267 | switch (esp->dma->revision) { | 275 | switch (esp->dmarev) { |
268 | case dvmahme: | 276 | case dvmahme: |
269 | dma_write32(DMA_RESET_FAS366, DMA_CSR); | 277 | dma_write32(DMA_RESET_FAS366, DMA_CSR); |
270 | dma_write32(DMA_RST_SCSI, DMA_CSR); | 278 | dma_write32(DMA_RST_SCSI, DMA_CSR); |
@@ -346,14 +354,14 @@ static void sbus_esp_dma_drain(struct esp *esp) | |||
346 | u32 csr; | 354 | u32 csr; |
347 | int lim; | 355 | int lim; |
348 | 356 | ||
349 | if (esp->dma->revision == dvmahme) | 357 | if (esp->dmarev == dvmahme) |
350 | return; | 358 | return; |
351 | 359 | ||
352 | csr = dma_read32(DMA_CSR); | 360 | csr = dma_read32(DMA_CSR); |
353 | if (!(csr & DMA_FIFO_ISDRAIN)) | 361 | if (!(csr & DMA_FIFO_ISDRAIN)) |
354 | return; | 362 | return; |
355 | 363 | ||
356 | if (esp->dma->revision != dvmarev3 && esp->dma->revision != dvmaesc1) | 364 | if (esp->dmarev != dvmarev3 && esp->dmarev != dvmaesc1) |
357 | dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR); | 365 | dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR); |
358 | 366 | ||
359 | lim = 1000; | 367 | lim = 1000; |
@@ -369,7 +377,7 @@ static void sbus_esp_dma_drain(struct esp *esp) | |||
369 | 377 | ||
370 | static void sbus_esp_dma_invalidate(struct esp *esp) | 378 | static void sbus_esp_dma_invalidate(struct esp *esp) |
371 | { | 379 | { |
372 | if (esp->dma->revision == dvmahme) { | 380 | if (esp->dmarev == dvmahme) { |
373 | dma_write32(DMA_RST_SCSI, DMA_CSR); | 381 | dma_write32(DMA_RST_SCSI, DMA_CSR); |
374 | 382 | ||
375 | esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | | 383 | esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | |
@@ -440,7 +448,7 @@ static void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, | |||
440 | else | 448 | else |
441 | csr &= ~DMA_ST_WRITE; | 449 | csr &= ~DMA_ST_WRITE; |
442 | dma_write32(csr, DMA_CSR); | 450 | dma_write32(csr, DMA_CSR); |
443 | if (esp->dma->revision == dvmaesc1) { | 451 | if (esp->dmarev == dvmaesc1) { |
444 | u32 end = PAGE_ALIGN(addr + dma_count + 16U); | 452 | u32 end = PAGE_ALIGN(addr + dma_count + 16U); |
445 | dma_write32(end - addr, DMA_COUNT); | 453 | dma_write32(end - addr, DMA_COUNT); |
446 | } | 454 | } |
@@ -478,7 +486,7 @@ static const struct esp_driver_ops sbus_esp_ops = { | |||
478 | 486 | ||
479 | static int __devinit esp_sbus_probe_one(struct device *dev, | 487 | static int __devinit esp_sbus_probe_one(struct device *dev, |
480 | struct sbus_dev *esp_dev, | 488 | struct sbus_dev *esp_dev, |
481 | struct sbus_dev *espdma, | 489 | struct of_device *espdma, |
482 | struct sbus_bus *sbus, | 490 | struct sbus_bus *sbus, |
483 | int hme) | 491 | int hme) |
484 | { | 492 | { |
@@ -503,7 +511,7 @@ static int __devinit esp_sbus_probe_one(struct device *dev, | |||
503 | if (hme) | 511 | if (hme) |
504 | esp->flags |= ESP_FLAG_WIDE_CAPABLE; | 512 | esp->flags |= ESP_FLAG_WIDE_CAPABLE; |
505 | 513 | ||
506 | err = esp_sbus_find_dma(esp, espdma); | 514 | err = esp_sbus_setup_dma(esp, espdma); |
507 | if (err < 0) | 515 | if (err < 0) |
508 | goto fail_unlink; | 516 | goto fail_unlink; |
509 | 517 | ||
@@ -525,7 +533,7 @@ static int __devinit esp_sbus_probe_one(struct device *dev, | |||
525 | * come up with the reset bit set, so make sure that | 533 | * come up with the reset bit set, so make sure that |
526 | * is clear first. | 534 | * is clear first. |
527 | */ | 535 | */ |
528 | if (esp->dma->revision == dvmaesc1) { | 536 | if (esp->dmarev == dvmaesc1) { |
529 | u32 val = dma_read32(DMA_CSR); | 537 | u32 val = dma_read32(DMA_CSR); |
530 | 538 | ||
531 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); | 539 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); |
@@ -556,26 +564,32 @@ fail: | |||
556 | static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 564 | static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match) |
557 | { | 565 | { |
558 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | 566 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); |
567 | struct device_node *dma_node = NULL; | ||
559 | struct device_node *dp = dev->node; | 568 | struct device_node *dp = dev->node; |
560 | struct sbus_dev *dma_sdev = NULL; | 569 | struct of_device *dma_of = NULL; |
561 | int hme = 0; | 570 | int hme = 0; |
562 | 571 | ||
563 | if (dp->parent && | 572 | if (dp->parent && |
564 | (!strcmp(dp->parent->name, "espdma") || | 573 | (!strcmp(dp->parent->name, "espdma") || |
565 | !strcmp(dp->parent->name, "dma"))) | 574 | !strcmp(dp->parent->name, "dma"))) |
566 | dma_sdev = sdev->parent; | 575 | dma_node = dp->parent; |
567 | else if (!strcmp(dp->name, "SUNW,fas")) { | 576 | else if (!strcmp(dp->name, "SUNW,fas")) { |
568 | dma_sdev = sdev; | 577 | dma_node = sdev->ofdev.node; |
569 | hme = 1; | 578 | hme = 1; |
570 | } | 579 | } |
580 | if (dma_node) | ||
581 | dma_of = of_find_device_by_node(dma_node); | ||
582 | if (!dma_of) | ||
583 | return -ENODEV; | ||
571 | 584 | ||
572 | return esp_sbus_probe_one(&dev->dev, sdev, dma_sdev, | 585 | return esp_sbus_probe_one(&dev->dev, sdev, dma_of, |
573 | sdev->bus, hme); | 586 | sdev->bus, hme); |
574 | } | 587 | } |
575 | 588 | ||
576 | static int __devexit esp_sbus_remove(struct of_device *dev) | 589 | static int __devexit esp_sbus_remove(struct of_device *dev) |
577 | { | 590 | { |
578 | struct esp *esp = dev_get_drvdata(&dev->dev); | 591 | struct esp *esp = dev_get_drvdata(&dev->dev); |
592 | struct of_device *dma_of = esp->dma; | ||
579 | unsigned int irq = esp->host->irq; | 593 | unsigned int irq = esp->host->irq; |
580 | u32 val; | 594 | u32 val; |
581 | 595 | ||
@@ -590,6 +604,8 @@ static int __devexit esp_sbus_remove(struct of_device *dev) | |||
590 | esp->command_block, | 604 | esp->command_block, |
591 | esp->command_block_dma); | 605 | esp->command_block_dma); |
592 | sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE); | 606 | sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE); |
607 | of_iounmap(&dma_of->resource[0], esp->dma_regs, | ||
608 | resource_size(&dma_of->resource[0])); | ||
593 | 609 | ||
594 | scsi_host_put(esp->host); | 610 | scsi_host_put(esp->host); |
595 | 611 | ||