drm/nouveau/clk/gk20a: setup slide once during init
authorAlexandre Courbot <acourbot@nvidia.com>
Wed, 1 Jun 2016 08:39:21 +0000 (17:39 +0900)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 14 Jul 2016 01:53:25 +0000 (11:53 +1000)
Slide setup needs to be performed only once, during init. Also
use the proper parameters for different clock speeds.

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
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.h
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c

index d633669..166f51c 100644 (file)
@@ -274,12 +274,6 @@ gk20a_pllg_slide(struct gk20a_clk *clk, u32 n)
        if (n == ((val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH)))
                return 0;
 
-       /* setup */
-       nvkm_mask(device, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT,
-               0x2b << GPCPLL_CFG2_PLL_STEPA_SHIFT);
-       nvkm_mask(device, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT,
-               0xb << GPCPLL_CFG3_PLL_STEPB_SHIFT);
-
        /* pll slowdown mode */
        nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
                BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT),
@@ -581,6 +575,42 @@ gk20a_clk_tidy(struct nvkm_clk *base)
 {
 }
 
+int
+gk20a_clk_setup_slide(struct gk20a_clk *clk)
+{
+       struct nvkm_subdev *subdev = &clk->base.subdev;
+       struct nvkm_device *device = subdev->device;
+       u32 step_a, step_b;
+
+       switch (clk->parent_rate) {
+       case 12000000:
+       case 12800000:
+       case 13000000:
+               step_a = 0x2b;
+               step_b = 0x0b;
+               break;
+       case 19200000:
+               step_a = 0x12;
+               step_b = 0x08;
+               break;
+       case 38400000:
+               step_a = 0x04;
+               step_b = 0x05;
+               break;
+       default:
+               nvkm_error(subdev, "invalid parent clock rate %u KHz",
+                          clk->parent_rate / KHZ);
+               return -EINVAL;
+       }
+
+       nvkm_mask(device, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT,
+               step_a << GPCPLL_CFG2_PLL_STEPA_SHIFT);
+       nvkm_mask(device, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT,
+               step_b << GPCPLL_CFG3_PLL_STEPB_SHIFT);
+
+       return 0;
+}
+
 void
 gk20a_clk_fini(struct nvkm_clk *base)
 {
@@ -617,6 +647,10 @@ gk20a_clk_init(struct nvkm_clk *base)
        nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK,
                  GPC2CLK_OUT_INIT_VAL);
 
+       ret = gk20a_clk_setup_slide(clk);
+       if (ret)
+               return ret;
+
        /* Start with lowest frequency */
        base->func->calc(base, &base->func->pstates[0].base);
        ret = base->func->prog(&clk->base);
index 13c4674..028c272 100644 (file)
@@ -62,4 +62,6 @@ int gk20a_clk_calc(struct nvkm_clk *, struct nvkm_cstate *);
 int gk20a_clk_prog(struct nvkm_clk *);
 void gk20a_clk_tidy(struct nvkm_clk *);
 
+int gk20a_clk_setup_slide(struct gk20a_clk *);
+
 #endif
index 274a74c..a34acaf 100644 (file)
@@ -144,6 +144,10 @@ gm20b_clk_init(struct nvkm_clk *base)
        struct nvkm_device *device = subdev->device;
        int ret;
 
+       ret = gk20a_clk_setup_slide(clk);
+       if (ret)
+               return ret;
+
        /* Set the global bypass control to VCO */
        nvkm_mask(device, BYPASSCTRL_SYS,
               MASK(BYPASSCTRL_SYS_GPCPLL_WIDTH) << BYPASSCTRL_SYS_GPCPLL_SHIFT,