static int gk20a_clk_init(struct nvkm_clk *base) { struct gk20a_clk *clk = gk20a_clk(base); struct nvkm_subdev *subdev = &clk->base.subdev; struct nvkm_device *device = subdev->device; int ret; /* get out from IDDQ */ nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_IDDQ, 0); nvkm_rd32(device, GPCPLL_CFG); udelay(5); 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); if (ret) { nvkm_error(subdev, "cannot initialize clock\n"); return ret; } return 0; }
int gk20a_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate) { struct gk20a_clk *clk = gk20a_clk(base); return gk20a_pllg_calc_mnp(clk, cstate->domain[nv_clk_src_gpc] * GK20A_CLK_GPC_MDIV, &clk->pll); }
int gk20a_clk_prog(struct nvkm_clk *base) { struct gk20a_clk *clk = gk20a_clk(base); int ret; ret = gk20a_pllg_program_mnp_slide(clk, &clk->pll); if (ret) ret = gk20a_pllg_program_mnp(clk, &clk->pll); return ret; }
int gk20a_clk_read(struct nvkm_clk *base, enum nv_clk_src src) { struct gk20a_clk *clk = gk20a_clk(base); struct nvkm_subdev *subdev = &clk->base.subdev; struct nvkm_device *device = subdev->device; struct gk20a_pll pll; switch (src) { case nv_clk_src_crystal: return device->crystal; case nv_clk_src_gpc: gk20a_pllg_read_mnp(clk, &pll); return gk20a_pllg_calc_rate(clk, &pll) / GK20A_CLK_GPC_MDIV; default: nvkm_error(subdev, "invalid clock source %d\n", src); return -EINVAL; } }
void gk20a_clk_fini(struct nvkm_clk *base) { struct nvkm_device *device = base->subdev.device; struct gk20a_clk *clk = gk20a_clk(base); /* slide to VCO min */ if (gk20a_pllg_is_enabled(clk)) { struct gk20a_pll pll; u32 n_lo; gk20a_pllg_read_mnp(clk, &pll); n_lo = gk20a_pllg_n_lo(clk, &pll); gk20a_pllg_slide(clk, n_lo); } gk20a_pllg_disable(clk); /* set IDDQ */ nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_IDDQ, 1); }
static int gm20b_clk_init(struct nvkm_clk *base) { struct gk20a_clk *clk = gk20a_clk(base); struct nvkm_subdev *subdev = &clk->base.subdev; struct nvkm_device *device = subdev->device; int ret; /* Set the global bypass control to VCO */ nvkm_mask(device, BYPASSCTRL_SYS, MASK(BYPASSCTRL_SYS_GPCPLL_WIDTH) << BYPASSCTRL_SYS_GPCPLL_SHIFT, 0); /* Start with lowest frequency */ base->func->calc(base, &base->func->pstates[0].base); ret = base->func->prog(&clk->base); if (ret) { nvkm_error(subdev, "cannot initialize clock\n"); return ret; } return 0; }