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 /drivers/dma/omap-dma.c | |
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>
Diffstat (limited to 'drivers/dma/omap-dma.c')
-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); |