drm/tilcdc: Write DMA base and ceiling address with single instruction
authorJyri Sarha <jsarha@ti.com>
Fri, 26 Aug 2016 12:10:14 +0000 (15:10 +0300)
committerJyri Sarha <jsarha@ti.com>
Thu, 1 Sep 2016 19:31:59 +0000 (22:31 +0300)
Write DMA base and ceiling address with a single instruction, if
available. This should make it more unlikely that LCDC would fetch the
DMA addresses in the middle of an update. Having bad combination of
addresses in dma base and ceiling (e.g base > ceiling) can cause
unpredictaple behavior in LCDC.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/gpu/drm/tilcdc/tilcdc_regs.h

index 163f111cd48117fdbb09a511cdfd0c99404e6559..208768922030a7ff792fa958d772cb72f9ebb4cb 100644 (file)
@@ -69,6 +69,7 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
        struct drm_gem_cma_object *gem;
        unsigned int depth, bpp;
        dma_addr_t start, end;
+       u64 dma_base_and_ceiling;
 
        drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
        gem = drm_fb_cma_get_gem_obj(fb, 0);
@@ -79,8 +80,13 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
 
        end = start + (crtc->mode.vdisplay * fb->pitches[0]);
 
-       tilcdc_write(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, start);
-       tilcdc_write(dev, LCDC_DMA_FB_CEILING_ADDR_0_REG, end - 1);
+       /* Write LCDC_DMA_FB_BASE_ADDR_0_REG and LCDC_DMA_FB_CEILING_ADDR_0_REG
+        * with a single insruction, if available. This should make it more
+        * unlikely that LCDC would fetch the DMA addresses in the middle of
+        * an update.
+        */
+       dma_base_and_ceiling = (u64)(end - 1) << 32 | start;
+       tilcdc_write64(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, dma_base_and_ceiling);
 
        if (tilcdc_crtc->curr_fb)
                drm_flip_work_queue(&tilcdc_crtc->unref_work,
index 1bf5e2553acc41062ae2754789d30025d05f9764..f57c0d62c76a23896d172bd1bbc54a60e7871172 100644 (file)
@@ -119,6 +119,20 @@ static inline void tilcdc_write(struct drm_device *dev, u32 reg, u32 data)
        iowrite32(data, priv->mmio + reg);
 }
 
+static inline void tilcdc_write64(struct drm_device *dev, u32 reg, u64 data)
+{
+       struct tilcdc_drm_private *priv = dev->dev_private;
+       volatile void __iomem *addr = priv->mmio + reg;
+
+#ifdef iowrite64
+       iowrite64(data, addr);
+#else
+       __iowmb();
+       /* This compiles to strd (=64-bit write) on ARM7 */
+       *(volatile u64 __force *)addr = __cpu_to_le64(data);
+#endif
+}
+
 static inline u32 tilcdc_read(struct drm_device *dev, u32 reg)
 {
        struct tilcdc_drm_private *priv = dev->dev_private;