diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-11-06 14:26:45 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-04-03 19:30:28 -0400 |
| commit | b07fd625ac9df7412bd996edbdc298eb343dd501 (patch) | |
| tree | 5330c6978b5d8b17f3dcc45b2e2b840874d6d213 | |
| parent | c5ed98b6ae79545284b7855a07ded32934865a6d (diff) | |
dmaengine: omap-dma: cleanup errata 3.3 handling
Provide a function to read the CSAC/CDAC register, working around the
OMAP 3.2/3.3 erratum (which requires two reads of the register if the
first returned zero.
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | drivers/dma/omap-dma.c | 52 |
1 files changed, 29 insertions, 23 deletions
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index a1baada7dcd4..1e0018f36384 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c | |||
| @@ -451,28 +451,39 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr) | |||
| 451 | return size; | 451 | return size; |
| 452 | } | 452 | } |
| 453 | 453 | ||
| 454 | /* | ||
| 455 | * OMAP 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is | ||
| 456 | * read before the DMA controller finished disabling the channel. | ||
| 457 | */ | ||
| 458 | static uint32_t omap_dma_chan_read_3_3(struct omap_chan *c, unsigned reg) | ||
| 459 | { | ||
| 460 | struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); | ||
| 461 | uint32_t val; | ||
| 462 | |||
| 463 | val = omap_dma_chan_read(c, reg); | ||
| 464 | if (val == 0 && od->plat->errata & DMA_ERRATA_3_3) | ||
| 465 | val = omap_dma_chan_read(c, reg); | ||
| 466 | |||
| 467 | return val; | ||
| 468 | } | ||
| 469 | |||
| 454 | static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) | 470 | static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) |
| 455 | { | 471 | { |
| 456 | struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); | 472 | struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); |
| 457 | dma_addr_t addr; | 473 | dma_addr_t addr, cdac; |
| 458 | 474 | ||
| 459 | if (__dma_omap15xx(od->plat->dma_attr)) | 475 | if (__dma_omap15xx(od->plat->dma_attr)) { |
| 460 | addr = omap_dma_chan_read(c, CPC); | 476 | addr = omap_dma_chan_read(c, CPC); |
| 461 | else | 477 | } else { |
| 462 | addr = omap_dma_chan_read(c, CSAC); | 478 | addr = omap_dma_chan_read_3_3(c, CSAC); |
| 463 | 479 | cdac = omap_dma_chan_read_3_3(c, CDAC); | |
| 464 | if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0) | ||
| 465 | addr = omap_dma_chan_read(c, CSAC); | ||
| 466 | 480 | ||
| 467 | if (!__dma_omap15xx(od->plat->dma_attr)) { | ||
| 468 | /* | 481 | /* |
| 469 | * CDAC == 0 indicates that the DMA transfer on the channel has | 482 | * CDAC == 0 indicates that the DMA transfer on the channel has |
| 470 | * not been started (no data has been transferred so far). | 483 | * not been started (no data has been transferred so far). |
| 471 | * Return the programmed source start address in this case. | 484 | * Return the programmed source start address in this case. |
| 472 | */ | 485 | */ |
| 473 | if (omap_dma_chan_read(c, CDAC)) | 486 | if (cdac == 0) |
| 474 | addr = omap_dma_chan_read(c, CSAC); | ||
| 475 | else | ||
| 476 | addr = omap_dma_chan_read(c, CSSA); | 487 | addr = omap_dma_chan_read(c, CSSA); |
| 477 | } | 488 | } |
| 478 | 489 | ||
| @@ -487,21 +498,16 @@ static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c) | |||
| 487 | struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); | 498 | struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); |
| 488 | dma_addr_t addr; | 499 | dma_addr_t addr; |
| 489 | 500 | ||
| 490 | if (__dma_omap15xx(od->plat->dma_attr)) | 501 | if (__dma_omap15xx(od->plat->dma_attr)) { |
| 491 | addr = omap_dma_chan_read(c, CPC); | 502 | addr = omap_dma_chan_read(c, CPC); |
| 492 | else | 503 | } else { |
| 493 | addr = omap_dma_chan_read(c, CDAC); | 504 | addr = omap_dma_chan_read_3_3(c, CDAC); |
| 494 | 505 | ||
| 495 | /* | ||
| 496 | * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is | ||
| 497 | * read before the DMA controller finished disabling the channel. | ||
| 498 | */ | ||
| 499 | if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) { | ||
| 500 | addr = omap_dma_chan_read(c, CDAC); | ||
| 501 | /* | 506 | /* |
| 502 | * CDAC == 0 indicates that the DMA transfer on the channel has | 507 | * CDAC == 0 indicates that the DMA transfer on the channel |
| 503 | * not been started (no data has been transferred so far). | 508 | * has not been started (no data has been transferred so |
| 504 | * Return the programmed destination start address in this case. | 509 | * far). Return the programmed destination start address in |
| 510 | * this case. | ||
| 505 | */ | 511 | */ |
| 506 | if (addr == 0) | 512 | if (addr == 0) |
| 507 | addr = omap_dma_chan_read(c, CDSA); | 513 | addr = omap_dma_chan_read(c, CDSA); |
