]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
mailbox: bcm-pdc: Changes so mbox client can be removed / re-inserted
authorSteve Lin <steven.lin1@broadcom.com>
Mon, 14 Nov 2016 18:25:56 +0000 (13:25 -0500)
committerJassi Brar <jaswinder.singh@linaro.org>
Mon, 19 Dec 2016 14:40:18 +0000 (20:10 +0530)
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 <steven.lin1@broadcom.com>
Signed-off-by: Rob Rice <rob.rice@broadcom.com>
Reviewed-by: Andy Gospodarek <gospo@broadcom.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
drivers/mailbox/bcm-pdc-mailbox.c

index a9c804fa3fbe646a0a8eea07d642fd2a3b65ca1c..3b4ebbe819643153561e7001de269b0a58c9b99d 100644 (file)
 
 /*
  * 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
  * 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,22 +1253,40 @@ 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.
@@ -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);