static int tsi721_bdma_maint_init()

in devices/tsi721.c [1417:1503]


static int tsi721_bdma_maint_init(struct tsi721_device *priv)
{
	struct tsi721_dma_desc *bd_ptr;
	u64		*sts_ptr;
	dma_addr_t	bd_phys, sts_phys;
	int		sts_size;
	int		bd_num = 2;
	void __iomem	*regs;

	tsi_debug(MAINT, &priv->pdev->dev,
		  "Init BDMA_%d Maintenance requests", TSI721_DMACH_MAINT);

	/*
	 * Initialize DMA channel for maintenance requests
	 */

	priv->mdma.ch_id = TSI721_DMACH_MAINT;
	regs = priv->regs + TSI721_DMAC_BASE(TSI721_DMACH_MAINT);

	/* Allocate space for DMA descriptors */
	bd_ptr = dma_alloc_coherent(&priv->pdev->dev,
				    bd_num * sizeof(struct tsi721_dma_desc),
				    &bd_phys, GFP_KERNEL);
	if (!bd_ptr)
		return -ENOMEM;

	priv->mdma.bd_num = bd_num;
	priv->mdma.bd_phys = bd_phys;
	priv->mdma.bd_base = bd_ptr;

	tsi_debug(MAINT, &priv->pdev->dev, "DMA descriptors @ %p (phys = %pad)",
		  bd_ptr, &bd_phys);

	/* Allocate space for descriptor status FIFO */
	sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ?
					bd_num : TSI721_DMA_MINSTSSZ;
	sts_size = roundup_pow_of_two(sts_size);
	sts_ptr = dma_alloc_coherent(&priv->pdev->dev,
				     sts_size * sizeof(struct tsi721_dma_sts),
				     &sts_phys, GFP_KERNEL);
	if (!sts_ptr) {
		/* Free space allocated for DMA descriptors */
		dma_free_coherent(&priv->pdev->dev,
				  bd_num * sizeof(struct tsi721_dma_desc),
				  bd_ptr, bd_phys);
		priv->mdma.bd_base = NULL;
		return -ENOMEM;
	}

	priv->mdma.sts_phys = sts_phys;
	priv->mdma.sts_base = sts_ptr;
	priv->mdma.sts_size = sts_size;

	tsi_debug(MAINT, &priv->pdev->dev,
		"desc status FIFO @ %p (phys = %pad) size=0x%x",
		sts_ptr, &sts_phys, sts_size);

	/* Initialize DMA descriptors ring */
	bd_ptr[bd_num - 1].type_id = cpu_to_le32(DTYPE3 << 29);
	bd_ptr[bd_num - 1].next_lo = cpu_to_le32((u64)bd_phys &
						 TSI721_DMAC_DPTRL_MASK);
	bd_ptr[bd_num - 1].next_hi = cpu_to_le32((u64)bd_phys >> 32);

	/* Setup DMA descriptor pointers */
	iowrite32(((u64)bd_phys >> 32),	regs + TSI721_DMAC_DPTRH);
	iowrite32(((u64)bd_phys & TSI721_DMAC_DPTRL_MASK),
		regs + TSI721_DMAC_DPTRL);

	/* Setup descriptor status FIFO */
	iowrite32(((u64)sts_phys >> 32), regs + TSI721_DMAC_DSBH);
	iowrite32(((u64)sts_phys & TSI721_DMAC_DSBL_MASK),
		regs + TSI721_DMAC_DSBL);
	iowrite32(TSI721_DMAC_DSSZ_SIZE(sts_size),
		regs + TSI721_DMAC_DSSZ);

	/* Clear interrupt bits */
	iowrite32(TSI721_DMAC_INT_ALL, regs + TSI721_DMAC_INT);

	ioread32(regs + TSI721_DMAC_INT);

	/* Toggle DMA channel initialization */
	iowrite32(TSI721_DMAC_CTL_INIT,	regs + TSI721_DMAC_CTL);
	ioread32(regs + TSI721_DMAC_CTL);
	udelay(10);

	return 0;
}