/* s3c_dma_loadbuffer * * load a buffer, and update the channel state */ static inline int s3c_dma_loadbuffer(struct s3c2410_dma_chan *chan, struct s3c_dma_buf *buf) { unsigned long reload; pr_debug("s3c_chan_loadbuffer: loading buffer %p (0x%08lx,0x%06x)\n", buf, (unsigned long) buf->data, buf->size); if (buf == NULL) { dmawarn("buffer is NULL\n"); return -EINVAL; } /* check the state of the channel before we do anything */ if (chan->load_state == S3C_DMALOAD_1LOADED) { dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n"); reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0; } if (chan->load_state == S3C_DMALOAD_1LOADED_1RUNNING) { dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n"); reload = S3C2410_DCON_AUTORELOAD; } writel(buf->data, chan->addr_reg); pr_debug("%s: DMA control0 - %08x\n", __FUNCTION__, chan->dcon); pr_debug("%s: DMA control1 - %08x\n", __FUNCTION__, (buf->size / chan->xfer_unit)); dma_wrreg(chan, S3C_DMAC_CxCONTROL0, chan->dcon); dma_wrreg(chan, S3C_DMAC_CxCONTROL1, (buf->size / chan->xfer_unit)); chan->next = buf->next; /* update the state of the channel */ switch (chan->load_state) { case S3C_DMALOAD_NONE: chan->load_state = S3C_DMALOAD_1LOADED; break; case S3C_DMALOAD_1RUNNING: chan->load_state = S3C_DMALOAD_1LOADED_1RUNNING; break; default: dmawarn("dmaload: unknown state %d in loadbuffer\n", chan->load_state); break; } return 0; }
static inline int s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf) { unsigned long reload; pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n", buf, (unsigned long)buf->data, buf->size); if (buf == NULL) { dmawarn("buffer is NULL\n"); return -EINVAL; } /* check the state of the channel before we do anything */ if (chan->load_state == S3C2410_DMALOAD_1LOADED) { dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n"); } if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) { dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n"); } /* it would seem sensible if we are the last buffer to not bother * with the auto-reload bit, so that the DMA engine will not try * and load another transfer after this one has finished... */ if (chan->load_state == S3C2410_DMALOAD_NONE) { pr_debug("load_state is none, checking for noreload (next=%p)\n", buf->next); reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0; } else { //pr_debug("load_state is %d => autoreload\n", chan->load_state); reload = S3C2410_DCON_AUTORELOAD; } if ((buf->data & 0xf0000000) != 0x30000000) { dmawarn("dmaload: buffer is %p\n", (void *)buf->data); } writel(buf->data, chan->addr_reg); dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | reload | (buf->size/chan->xfer_unit)); chan->next = buf->next; /* update the state of the channel */ switch (chan->load_state) { case S3C2410_DMALOAD_NONE: chan->load_state = S3C2410_DMALOAD_1LOADED; break; case S3C2410_DMALOAD_1RUNNING: chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING; break; default: dmawarn("dmaload: unknown state %d in loadbuffer\n", chan->load_state); break; } return 0; }
/* s3c_dma_loadbuffer * * load a buffer, and update the channel state */ static inline int s3c_dma_loadbuffer(struct s3c2410_dma_chan *chan, struct s3c_dma_buf *buf) { unsigned long tmp; pl330_DMA_parameters_t dma_param; struct s3c_dma_buf *firstbuf; int bwJump = 0; memset(&dma_param, 0, sizeof(pl330_DMA_parameters_t)); pr_debug("s3c_chan_loadbuffer: loading buffer %p (0x%08lx,0x%06x)\n", buf, (unsigned long) buf->data, buf->size); if (buf == NULL) { dmawarn("buffer is NULL\n"); return -EINVAL; } pr_debug("%s: DMA CCR - %08x\n", __FUNCTION__, chan->dcon); pr_debug("%s: DMA Loop count - %08x\n", __FUNCTION__, (buf->size / chan->xfer_unit)); firstbuf = buf; do { dma_param.mPeriNum = chan->config_flags; dma_param.mDirection = chan->source; switch (dma_param.mDirection) { case S3C2410_DMASRC_MEM: /* source is Memory : Mem-to-Peri (Write into FIFO) */ dma_param.mSrcAddr = buf->data; dma_param.mDstAddr = chan->dev_addr; break; case S3C2410_DMASRC_HW: /* source is peripheral : Peri-to-Mem (Read from FIFO) */ dma_param.mSrcAddr = chan->dev_addr; dma_param.mDstAddr = buf->data; break; case S3C_DMA_MEM2MEM: /* source & Destination : Mem-to-Mem */ dma_param.mSrcAddr = chan->dev_addr; dma_param.mDstAddr = buf->data; break; case S3C_DMA_MEM2MEM_SET: /* source & Destination : Mem-to-Mem */ dma_param.mDirection = S3C_DMA_MEM2MEM; dma_param.mSrcAddr = chan->dev_addr; dma_param.mDstAddr = buf->data; break; case S3C_DMA_PER2PER: default: printk("Peripheral-to-Peripheral DMA NOT YET implemented !! \n"); return -EINVAL; } dma_param.mTrSize = buf->size; dma_param.mLoop = 0; dma_param.mControl = *(pl330_DMA_control_t *) &chan->dcon; chan->next = buf->next; buf = chan->next; if(buf==NULL) { firstbuf->next = NULL; dma_param.mLastReq = 1; dma_param.mIrqEnable = 1; } else { dma_param.mLastReq = 0; dma_param.mIrqEnable = 0; } bwJump += setup_DMA_channel(((u8 *)firstbuf->mcptr_cpu)+bwJump, dma_param, chan->number); pr_debug("%s: DMA bwJump - %d\n", __FUNCTION__, bwJump); }while(buf != NULL); if(dma_param.mIrqEnable) { tmp = dma_rdreg(chan->dma_con, S3C_DMAC_INTEN); tmp |= (1 << chan->number); dma_wrreg(chan->dma_con, S3C_DMAC_INTEN, tmp); } /* update the state of the channel */ switch (chan->load_state) { case S3C_DMALOAD_NONE: chan->load_state = S3C_DMALOAD_1LOADED; break; case S3C_DMALOAD_1RUNNING: chan->load_state = S3C_DMALOAD_1LOADED_1RUNNING; break; default: dmawarn("dmaload: unknown state %d in loadbuffer\n", chan->load_state); break; } return 0; }
static inline int samcop_dma_loadbuffer(samcop_dma_chan_t *chan, samcop_dma_buf_t *buf) { unsigned long reload; unsigned long tmp; if (buf == NULL) { dmawarn("buffer is NULL\n"); return -EINVAL; } pr_debug("samcop_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n", buf, (unsigned long)buf->data, buf->size); /* check the state of the channel before we do anything */ if (chan->load_state == SAMCOP_DMALOAD_1LOADED) { dmawarn("load_state is SAMCOP_DMALOAD_1LOADED\n"); } if (chan->load_state == SAMCOP_DMALOAD_1LOADED_1RUNNING) { dmawarn("state is SAMCOP_DMALOAD_1LOADED_1RUNNING\n"); } /* it would seem sensible if we are the last buffer to not bother * with the auto-reload bit, so that the DMA engine will not try * and load another transfer after this one has finished... */ if (chan->load_state == SAMCOP_DMALOAD_NONE) { pr_debug("load_state is none, checking for noreload (next=%p)\n", buf->next); reload = (buf->next == NULL) ? SAMCOP_DCON_NORELOAD : 0; } else { pr_debug("load_state is %d => autoreload\n", chan->load_state); reload = SAMCOP_DCON_AUTORELOAD; } /* Write the offset, preserving the INC and LOC bits. */ tmp = chan->rdreg(chan->regs, chan->addr_reg); tmp &= SAMCOP_DIxxx_INC_LOC_MASK; tmp |= buf->data & ~(SAMCOP_DIxxx_INC_LOC_MASK); chan->wrreg(chan->regs, chan->addr_reg, tmp); chan->wrreg(chan->regs, SAMCOP_DMA_DCON, chan->dcon | reload | (buf->size/chan->xfer_unit)); chan->next = buf->next; /* update the state of the channel */ switch (chan->load_state) { case SAMCOP_DMALOAD_NONE: chan->load_state = SAMCOP_DMALOAD_1LOADED; break; case SAMCOP_DMALOAD_1RUNNING: chan->load_state = SAMCOP_DMALOAD_1LOADED_1RUNNING; break; default: dmawarn("dmaload: unknown state %d in loadbuffer\n", chan->load_state); break; } return 0; }