]> rtime.felk.cvut.cz Git - vajnamar/linux-xlnx.git/commitdiff
dma: xilinx: Bug fix to ensure GPIO is reset between DMA operations
authorJeffrey Mouroux <jeff.mouroux@xilinx.com>
Tue, 29 Aug 2017 01:12:45 +0000 (18:12 -0700)
committerMichal Simek <michal.simek@xilinx.com>
Tue, 5 Sep 2017 12:21:46 +0000 (14:21 +0200)
Some registers within the Video Framebuffer driver, such as the
video format register, require a reset of the IP before they can
be altered.  Because there is no software accessible reset register,
an external GPIO is used.  This patch fixes a runtime issue wherein
clients wish to reprogram the IP for a new memory between DMA operations.
Without this fix, the Video Framebuffer Write IP may halt when a client
requests a new DMA operation using a different memory format for
writes to host memory.  In some cases, Framebuffer Read operations
will need to be reset when the downstream video pipeline is being
reset.

Signed-off-by: Jeffrey Mouroux <jmouroux@xilinx.com>
Reviewed-by: Hyun Kwon <hyun.kwon@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/dma/xilinx/xilinx_frmbuf.c

index e1f13dad38ee88b16bd2af04dcb6f35231a0ac0d..eb32e96948a849fc7f4c110132f605b25bd5d2f0 100644 (file)
@@ -650,7 +650,10 @@ static void xilinx_frmbuf_issue_pending(struct dma_chan *dchan)
  */
 static void xilinx_frmbuf_reset(struct xilinx_frmbuf_chan *chan)
 {
-       frmbuf_write(chan, XILINX_FRMBUF_CTRL_OFFSET, 0);
+       /* reset ip */
+       gpiod_set_value(chan->xdev->rst_gpio, 1);
+       udelay(1);
+       gpiod_set_value(chan->xdev->rst_gpio, 0);
 }
 
 /**
@@ -660,9 +663,8 @@ static void xilinx_frmbuf_reset(struct xilinx_frmbuf_chan *chan)
 static void xilinx_frmbuf_chan_reset(struct xilinx_frmbuf_chan *chan)
 {
        xilinx_frmbuf_reset(chan);
-
-       frmbuf_set(chan, XILINX_FRMBUF_IE_OFFSET,
-                  XILINX_FRMBUF_ISR_ALL_IRQ_MASK);
+       frmbuf_write(chan, XILINX_FRMBUF_IE_OFFSET, XILINX_FRMBUF_IE_AP_READY);
+       frmbuf_write(chan, XILINX_FRMBUF_GIE_OFFSET, XILINX_FRMBUF_GIE_EN);
 }
 
 /**
@@ -792,6 +794,9 @@ static int xilinx_frmbuf_terminate_all(struct dma_chan *dchan)
 
        xilinx_frmbuf_halt(chan);
        xilinx_frmbuf_free_descriptors(chan);
+       /* worst case frame-to-frame boundary; ensure frame output complete */
+       msleep(50);
+       xilinx_frmbuf_chan_reset(chan);
 
        return 0;
 }
@@ -894,9 +899,6 @@ static int xilinx_frmbuf_chan_probe(struct xilinx_frmbuf_device *xdev,
 
        xilinx_frmbuf_chan_reset(chan);
 
-       frmbuf_write(chan, XILINX_FRMBUF_IE_OFFSET, XILINX_FRMBUF_IE_AP_READY);
-       frmbuf_write(chan, XILINX_FRMBUF_GIE_OFFSET, XILINX_FRMBUF_GIE_EN);
-
        return 0;
 }