static int pdc_ring_init()

in bcm-pdc-mailbox.c [984:1081]


static int pdc_ring_init(struct pdc_state *pdcs, int ringset)
{
	int i;
	int err = PDC_SUCCESS;
	struct dma64 *dma_reg;
	struct device *dev = &pdcs->pdev->dev;
	struct pdc_ring_alloc tx;
	struct pdc_ring_alloc rx;

	/* Allocate tx ring */
	tx.vbase = dma_pool_zalloc(pdcs->ring_pool, GFP_KERNEL, &tx.dmabase);
	if (unlikely(!tx.vbase)) {
		err = -ENOMEM;
		goto done;
	}

	/* Allocate rx ring */
	rx.vbase = dma_pool_zalloc(pdcs->ring_pool, GFP_KERNEL, &rx.dmabase);
	if (unlikely(!rx.vbase)) {
		err = -ENOMEM;
		goto fail_dealloc;
	}

	dev_dbg(dev, " - base DMA addr of tx ring      %pad", &tx.dmabase);
	dev_dbg(dev, " - base virtual addr of tx ring  %p", tx.vbase);
	dev_dbg(dev, " - base DMA addr of rx ring      %pad", &rx.dmabase);
	dev_dbg(dev, " - base virtual addr of rx ring  %p", rx.vbase);

	memcpy(&pdcs->tx_ring_alloc, &tx, sizeof(tx));
	memcpy(&pdcs->rx_ring_alloc, &rx, sizeof(rx));

	pdcs->rxin = 0;
	pdcs->rx_msg_start = 0;
	pdcs->last_rx_curr = 0;
	pdcs->rxout = 0;
	pdcs->txin = 0;
	pdcs->tx_msg_start = 0;
	pdcs->txout = 0;

	/* Set descriptor array base addresses */
	pdcs->txd_64 = (struct dma64dd *)pdcs->tx_ring_alloc.vbase;
	pdcs->rxd_64 = (struct dma64dd *)pdcs->rx_ring_alloc.vbase;

	/* Tell device the base DMA address of each ring */
	dma_reg = &pdcs->regs->dmaregs[ringset];

	/* But first disable DMA and set curptr to 0 for both TX & RX */
	iowrite32(PDC_TX_CTL, &dma_reg->dmaxmt.control);
	iowrite32((PDC_RX_CTL + (pdcs->rx_status_len << 1)),
		  &dma_reg->dmarcv.control);
	iowrite32(0, &dma_reg->dmaxmt.ptr);
	iowrite32(0, &dma_reg->dmarcv.ptr);

	/* Set base DMA addresses */
	iowrite32(lower_32_bits(pdcs->tx_ring_alloc.dmabase),
		  &dma_reg->dmaxmt.addrlow);
	iowrite32(upper_32_bits(pdcs->tx_ring_alloc.dmabase),
		  &dma_reg->dmaxmt.addrhigh);

	iowrite32(lower_32_bits(pdcs->rx_ring_alloc.dmabase),
		  &dma_reg->dmarcv.addrlow);
	iowrite32(upper_32_bits(pdcs->rx_ring_alloc.dmabase),
		  &dma_reg->dmarcv.addrhigh);

	/* Re-enable DMA */
	iowrite32(PDC_TX_CTL | PDC_TX_ENABLE, &dma_reg->dmaxmt.control);
	iowrite32((PDC_RX_CTL | PDC_RX_ENABLE | (pdcs->rx_status_len << 1)),
		  &dma_reg->dmarcv.control);

	/* Initialize descriptors */
	for (i = 0; i < PDC_RING_ENTRIES; i++) {
		/* Every tx descriptor can be used for start of frame. */
		if (i != pdcs->ntxpost) {
			iowrite32(D64_CTRL1_SOF | D64_CTRL1_EOF,
				  &pdcs->txd_64[i].ctrl1);
		} else {
			/* Last descriptor in ringset. Set End of Table. */
			iowrite32(D64_CTRL1_SOF | D64_CTRL1_EOF |
				  D64_CTRL1_EOT, &pdcs->txd_64[i].ctrl1);
		}

		/* Every rx descriptor can be used for start of frame */
		if (i != pdcs->nrxpost) {
			iowrite32(D64_CTRL1_SOF,
				  &pdcs->rxd_64[i].ctrl1);
		} else {
			/* Last descriptor in ringset. Set End of Table. */
			iowrite32(D64_CTRL1_SOF | D64_CTRL1_EOT,
				  &pdcs->rxd_64[i].ctrl1);
		}
	}
	return PDC_SUCCESS;

fail_dealloc:
	dma_pool_free(pdcs->ring_pool, tx.vbase, tx.dmabase);
done:
	return err;
}