drm/nouveau/clk/gk20a: only restore divider to 1:1 if needed
authorAlexandre Courbot <acourbot@nvidia.com>
Fri, 12 Feb 2016 05:19:27 +0000 (14:19 +0900)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 14 Mar 2016 00:13:53 +0000 (10:13 +1000)
Only restore the 1:1 divider if it is not set already. Also use the
proper masks for this operation and add a second write as done in the
Android code.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c

index e72e20a0d009764acb9ede2f7c1c3c49f031a214..0746bb3e3075eac637d30c4e2bd0ef3af7cfdcfc 100644 (file)
@@ -429,9 +429,16 @@ _gk20a_pllg_program_mnp(struct gk20a_clk *clk, bool allow_slide)
 
        /* restore out divider 1:1 */
        val = nvkm_rd32(device, GPC2CLK_OUT);
-       val &= ~GPC2CLK_OUT_VCODIV_MASK;
-       udelay(2);
-       nvkm_wr32(device, GPC2CLK_OUT, val);
+       if ((val & GPC2CLK_OUT_VCODIV_MASK) !=
+           (GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT)) {
+               val &= ~GPC2CLK_OUT_VCODIV_MASK;
+               val |= GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT;
+               udelay(2);
+               nvkm_wr32(device, GPC2CLK_OUT, val);
+               /* Intentional 2nd write to assure linear divider operation */
+               nvkm_wr32(device, GPC2CLK_OUT, val);
+               nvkm_rd32(device, GPC2CLK_OUT);
+       }
 
        /* slide up to new NDIV */
        return allow_slide ? gk20a_pllg_slide(clk, clk->n) : 0;