Exemple #1
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 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;
}
Exemple #2
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;
}
Exemple #4
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;
}