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;
}