From 9fb0f9ac54b393ddfe49be7da7751f02bb133db6 Mon Sep 17 00:00:00 2001 From: Steve Lin Date: Mon, 14 Nov 2016 13:25:56 -0500 Subject: [PATCH] mailbox: bcm-pdc: Changes so mbox client can be removed / re-inserted Ensure that DMA is disabled, and pointers reset, when changing DMA base addresses in pdc_ring_init(). This allows a mailbox client to be re-inserted after being removed. Otherwise, the DMA doesn't restart so the client hangs while being reinserted. Signed-off-by: Steve Lin Signed-off-by: Rob Rice Reviewed-by: Andy Gospodarek Signed-off-by: Jassi Brar --- drivers/mailbox/bcm-pdc-mailbox.c | 54 +++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/drivers/mailbox/bcm-pdc-mailbox.c b/drivers/mailbox/bcm-pdc-mailbox.c index a9c804f..3b4ebbe 100644 --- a/drivers/mailbox/bcm-pdc-mailbox.c +++ b/drivers/mailbox/bcm-pdc-mailbox.c @@ -117,15 +117,16 @@ /* * Sets the following bits for write to transmit control reg: - * 0 - XmtEn - enable activity on the tx channel * 11 - PtyChkDisable - parity check is disabled * 20:18 - BurstLen = 3 -> 2^7 = 128 byte data reads from memory */ -#define PDC_TX_CTL 0x000C0801 +#define PDC_TX_CTL 0x000C0800 + +/* Bit in tx control reg to enable tx channel */ +#define PDC_TX_ENABLE 0x1 /* * Sets the following bits for write to receive control reg: - * 0 - RcvEn - enable activity on the rx channel * 7:1 - RcvOffset - size in bytes of status region at start of rx frame buf * 9 - SepRxHdrDescEn - place start of new frames only in descriptors * that have StartOfFrame set @@ -135,7 +136,10 @@ * 11 - PtyChkDisable - parity check is disabled * 20:18 - BurstLen = 3 -> 2^7 = 128 byte data reads from memory */ -#define PDC_RX_CTL 0x000C0E01 +#define PDC_RX_CTL 0x000C0E00 + +/* Bit in rx control reg to enable rx channel */ +#define PDC_RX_ENABLE 0x1 #define CRYPTO_D64_RS0_CD_MASK ((PDC_RING_ENTRIES * RING_ENTRY_SIZE) - 1) @@ -1054,6 +1058,15 @@ static int pdc_ring_init(struct pdc_state *pdcs, int ringset) /* 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)), + (void *)&dma_reg->dmarcv.control); + iowrite32(0, (void *)&dma_reg->dmaxmt.ptr); + iowrite32(0, (void *)&dma_reg->dmarcv.ptr); + + /* Set base DMA addresses */ iowrite32(lower_32_bits(pdcs->tx_ring_alloc.dmabase), (void *)&dma_reg->dmaxmt.addrlow); iowrite32(upper_32_bits(pdcs->tx_ring_alloc.dmabase), @@ -1064,6 +1077,11 @@ static int pdc_ring_init(struct pdc_state *pdcs, int ringset) iowrite32(upper_32_bits(pdcs->rx_ring_alloc.dmabase), (void *)&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)), + (void *)&dma_reg->dmarcv.control); + /* Initialize descriptors */ for (i = 0; i < PDC_RING_ENTRIES; i++) { /* Every tx descriptor can be used for start of frame. */ @@ -1235,23 +1253,41 @@ void pdc_hw_init(struct pdc_state *pdcs) pdcs->nrxd = PDC_RING_ENTRIES; pdcs->ntxpost = PDC_RING_ENTRIES - 1; pdcs->nrxpost = PDC_RING_ENTRIES - 1; - pdcs->regs->intmask = 0; + iowrite32(0, &pdcs->regs->intmask); dma_reg = &pdcs->regs->dmaregs[ringset]; - iowrite32(0, (void *)&dma_reg->dmaxmt.ptr); - iowrite32(0, (void *)&dma_reg->dmarcv.ptr); - iowrite32(PDC_TX_CTL, (void *)&dma_reg->dmaxmt.control); + /* Configure DMA but will enable later in pdc_ring_init() */ + iowrite32(PDC_TX_CTL, &dma_reg->dmaxmt.control); iowrite32(PDC_RX_CTL + (pdcs->rx_status_len << 1), (void *)&dma_reg->dmarcv.control); + /* Reset current index pointers after making sure DMA is disabled */ + iowrite32(0, &dma_reg->dmaxmt.ptr); + iowrite32(0, &dma_reg->dmarcv.ptr); + if (pdcs->pdc_resp_hdr_len == PDC_SPU2_RESP_HDR_LEN) iowrite32(PDC_CKSUM_CTRL, pdcs->pdc_reg_vbase + PDC_CKSUM_CTRL_OFFSET); } /** + * pdc_hw_disable() - Disable the tx and rx control in the hw. + * @pdcs: PDC state structure + * + */ +static void pdc_hw_disable(struct pdc_state *pdcs) +{ + struct dma64 *dma_reg; + + dma_reg = &pdcs->regs->dmaregs[PDC_RINGSET]; + iowrite32(PDC_TX_CTL, &dma_reg->dmaxmt.control); + iowrite32(PDC_RX_CTL + (pdcs->rx_status_len << 1), + &dma_reg->dmarcv.control); +} + +/** * pdc_rx_buf_pool_create() - Pool of receive buffers used to catch the metadata * header returned with each response message. * @pdcs: PDC state structure @@ -1505,6 +1541,8 @@ static int pdc_remove(struct platform_device *pdev) pdc_free_debugfs(); + pdc_hw_disable(pdcs); + mbox_controller_unregister(&pdcs->mbc); dma_pool_destroy(pdcs->rx_buf_pool); -- 2.7.4