diff options
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/omap-dma.c | 147 |
1 files changed, 61 insertions, 86 deletions
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index ec7cc10d459..9a9e8190747 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -58,8 +58,7 @@ struct omap_desc { int16_t fi; /* for OMAP_DMA_SYNC_PACKET */ uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */ - uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */ - uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */ + uint32_t ccr; /* CCR value */ uint16_t cicr; /* CICR value */ uint32_t csdp; /* CSDP value */ @@ -227,7 +226,6 @@ static void omap_dma_start_desc(struct omap_chan *c) { struct virt_dma_desc *vd = vchan_next_desc(&c->vc); struct omap_desc *d; - uint32_t val; if (!vd) { c->desc = NULL; @@ -239,23 +237,15 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d = to_omap_dma_desc(&vd->tx); c->sgidx = 0; - if (d->dir == DMA_DEV_TO_MEM) { - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 14 | 0x03 << 12); - val |= OMAP_DMA_AMODE_POST_INC << 14; - val |= OMAP_DMA_AMODE_CONSTANT << 12; - c->plat->dma_write(val, CCR, c->dma_ch); + c->plat->dma_write(d->ccr, CCR, c->dma_ch); + if (dma_omap1()) + c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch); + if (d->dir == DMA_DEV_TO_MEM) { c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch); c->plat->dma_write(0, CSEI, c->dma_ch); c->plat->dma_write(d->fi, CSFI, c->dma_ch); } else { - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(0x03 << 12 | 0x03 << 14); - val |= OMAP_DMA_AMODE_CONSTANT << 14; - val |= OMAP_DMA_AMODE_POST_INC << 12; - c->plat->dma_write(val, CCR, c->dma_ch); - c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch); c->plat->dma_write(0, CDEI, c->dma_ch); c->plat->dma_write(d->fi, CDFI, c->dma_ch); @@ -263,45 +253,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write(d->csdp, CSDP, c->dma_ch); - if (dma_omap1()) { - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(1 << 5); - if (d->sync_mode == OMAP_DMA_SYNC_FRAME) - val |= 1 << 5; - c->plat->dma_write(val, CCR, c->dma_ch); - - val = c->plat->dma_read(CCR2, c->dma_ch); - val &= ~(1 << 2); - if (d->sync_mode == OMAP_DMA_SYNC_BLOCK) - val |= 1 << 2; - c->plat->dma_write(val, CCR2, c->dma_ch); - } else if (c->dma_sig) { - val = c->plat->dma_read(CCR, c->dma_ch); - - /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ - val &= ~(1 << 24 | 1 << 23 | 3 << 19 | 1 << 18 | 1 << 5 | 0x1f); - val |= (c->dma_sig & ~0x1f) << 14; - val |= c->dma_sig & 0x1f; - - if (d->sync_mode & OMAP_DMA_SYNC_FRAME) - val |= 1 << 5; - - if (d->sync_mode & OMAP_DMA_SYNC_BLOCK) - val |= 1 << 18; - - switch (d->sync_type) { - case OMAP_DMA_DST_SYNC_PREFETCH:/* dest synch */ - val |= 1 << 23; /* Prefetch */ - break; - case 0: - break; - default: - val |= 1 << 24; /* source synch */ - break; - } - c->plat->dma_write(val, CCR, c->dma_ch); - } - omap_dma_start_sg(c, d, 0); } @@ -540,19 +491,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( struct scatterlist *sgent; struct omap_desc *d; dma_addr_t dev_addr; - unsigned i, j = 0, es, en, frame_bytes, sync_type; + unsigned i, j = 0, es, en, frame_bytes; u32 burst; if (dir == DMA_DEV_TO_MEM) { dev_addr = c->cfg.src_addr; dev_width = c->cfg.src_addr_width; burst = c->cfg.src_maxburst; - sync_type = OMAP_DMA_SRC_SYNC; } else if (dir == DMA_MEM_TO_DEV) { dev_addr = c->cfg.dst_addr; dev_width = c->cfg.dst_addr_width; burst = c->cfg.dst_maxburst; - sync_type = OMAP_DMA_DST_SYNC; } else { dev_err(chan->device->dev, "%s: bad direction?\n", __func__); return NULL; @@ -581,12 +530,28 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dir = dir; d->dev_addr = dev_addr; d->es = es; - d->sync_mode = OMAP_DMA_SYNC_FRAME; - d->sync_type = sync_type; + + d->ccr = 0; + if (dir == DMA_DEV_TO_MEM) + d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | + OMAP_DMA_AMODE_CONSTANT << 12; + else + d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | + OMAP_DMA_AMODE_POST_INC << 12; + d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; d->csdp = es; if (dma_omap1()) { + d->ccr |= 1 << 5; /* frame sync */ + if (__dma_omap16xx(od->plat->dma_attr)) { + d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + /* Duplicate what plat-omap/dma.c does */ + d->ccr |= c->dma_ch + 1; + } else { + d->ccr |= c->dma_sig & 0x1f; + } + d->cicr |= OMAP1_DMA_TOUT_IRQ; if (dir == DMA_DEV_TO_MEM) @@ -596,6 +561,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->csdp |= OMAP_DMA_PORT_TIPB << 9 | OMAP_DMA_PORT_EMIFF << 2; } else { + d->ccr |= (c->dma_sig & ~0x1f) << 14; + d->ccr |= c->dma_sig & 0x1f; + d->ccr |= 1 << 5; /* frame sync */ + + if (dir == DMA_DEV_TO_MEM) + d->ccr |= 1 << 24; /* source synch */ + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; } @@ -632,19 +604,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( enum dma_slave_buswidth dev_width; struct omap_desc *d; dma_addr_t dev_addr; - unsigned es, sync_type; + unsigned es; u32 burst; if (dir == DMA_DEV_TO_MEM) { dev_addr = c->cfg.src_addr; dev_width = c->cfg.src_addr_width; burst = c->cfg.src_maxburst; - sync_type = OMAP_DMA_SRC_SYNC; } else if (dir == DMA_MEM_TO_DEV) { dev_addr = c->cfg.dst_addr; dev_width = c->cfg.dst_addr_width; burst = c->cfg.dst_maxburst; - sync_type = OMAP_DMA_DST_SYNC; } else { dev_err(chan->device->dev, "%s: bad direction?\n", __func__); return NULL; @@ -674,15 +644,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->dev_addr = dev_addr; d->fi = burst; d->es = es; - if (burst) - d->sync_mode = OMAP_DMA_SYNC_PACKET; - else - d->sync_mode = OMAP_DMA_SYNC_ELEMENT; - d->sync_type = sync_type; d->sg[0].addr = buf_addr; d->sg[0].en = period_len / es_bytes[es]; d->sg[0].fn = buf_len / period_len; d->sglen = 1; + + d->ccr = 0; + if (__dma_omap15xx(od->plat->dma_attr)) + d->ccr = 3 << 8; + if (dir == DMA_DEV_TO_MEM) + d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 | + OMAP_DMA_AMODE_CONSTANT << 12; + else + d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 | + OMAP_DMA_AMODE_POST_INC << 12; + d->cicr = OMAP_DMA_DROP_IRQ; if (flags & DMA_PREP_INTERRUPT) d->cicr |= OMAP_DMA_FRAME_IRQ; @@ -690,6 +666,14 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp = es; if (dma_omap1()) { + if (__dma_omap16xx(od->plat->dma_attr)) { + d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */ + /* Duplicate what plat-omap/dma.c does */ + d->ccr |= c->dma_ch + 1; + } else { + d->ccr |= c->dma_sig & 0x1f; + } + d->cicr |= OMAP1_DMA_TOUT_IRQ; if (dir == DMA_DEV_TO_MEM) @@ -699,23 +683,22 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |= OMAP_DMA_PORT_MPUI << 9 | OMAP_DMA_PORT_EMIFF << 2; } else { + d->ccr |= (c->dma_sig & ~0x1f) << 14; + d->ccr |= c->dma_sig & 0x1f; + + if (burst) + d->ccr |= 1 << 18 | 1 << 5; /* packet */ + + if (dir == DMA_DEV_TO_MEM) + d->ccr |= 1 << 24; /* source synch */ + d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ; /* src and dst burst mode 16 */ d->csdp |= 3 << 14 | 3 << 7; } - if (!c->cyclic) { - c->cyclic = true; - - if (__dma_omap15xx(od->plat->dma_attr)) { - uint32_t val; - - val = c->plat->dma_read(CCR, c->dma_ch); - val |= 3 << 8; - c->plat->dma_write(val, CCR, c->dma_ch); - } - } + c->cyclic = true; return vchan_tx_prep(&c->vc, &d->vd, flags); } @@ -759,14 +742,6 @@ static int omap_dma_terminate_all(struct omap_chan *c) if (c->cyclic) { c->cyclic = false; c->paused = false; - - if (__dma_omap15xx(od->plat->dma_attr)) { - uint32_t val; - - val = c->plat->dma_read(CCR, c->dma_ch); - val &= ~(3 << 8); - c->plat->dma_write(val, CCR, c->dma_ch); - } } vchan_get_all_descriptors(&c->vc, &head); |