Loading drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +74 −8 Original line number Diff line number Diff line Loading @@ -136,12 +136,11 @@ static int nva3_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) { struct nva3_clock_priv *priv = (void *)clk; u32 hsrc; switch (src) { case nv_clk_src_crystal: return nv_device(priv)->crystal; case nv_clk_src_href: return 100000; case nv_clk_src_core: return read_pll(priv, 0x00, 0x4200); case nv_clk_src_shader: Loading @@ -154,6 +153,18 @@ nva3_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) return read_clk(priv, 0x21, false); case nv_clk_src_daemon: return read_clk(priv, 0x25, false); case nv_clk_src_host: hsrc = (nv_rd32(priv, 0xc040) & 0x30000000) >> 28; switch (hsrc) { case 0: return read_clk(priv, 0x1d, false); case 2: case 3: return 277000; default: nv_error(clk, "unknown HOST clock source %d\n", hsrc); return -EINVAL; } default: nv_error(clk, "invalid clock source %d\n", src); return -EINVAL; Loading Loading @@ -258,6 +269,34 @@ calc_clk(struct nva3_clock_priv *priv, struct nouveau_cstate *cstate, return ret; } static int calc_host(struct nva3_clock_priv *priv, struct nouveau_cstate *cstate) { int ret = 0; u32 kHz = cstate->domain[nv_clk_src_host]; struct nva3_clock_info *info = &priv->eng[nv_clk_src_host]; if (kHz == 277000) { info->clk = 0; info->host_out = NVA3_HOST_277; return 0; } info->host_out = NVA3_HOST_CLK; ret = nva3_clk_info(&priv->base, 0x1d, kHz, info); if (ret >= 0) return 0; return ret; } static void disable_clk_src(struct nva3_clock_priv *priv, u32 src) { nv_mask(priv, src, 0x00000100, 0x00000000); nv_mask(priv, src, 0x00000001, 0x00000000); } static void prog_pll(struct nva3_clock_priv *priv, int clk, u32 pll, int idx) { Loading @@ -275,15 +314,13 @@ prog_pll(struct nva3_clock_priv *priv, int clk, u32 pll, int idx) nv_wait(priv, ctrl, 0x00020000, 0x00020000); nv_mask(priv, ctrl, 0x00000010, 0x00000010); nv_mask(priv, ctrl, 0x00000008, 0x00000000); nv_mask(priv, src1, 0x00000100, 0x00000000); nv_mask(priv, src1, 0x00000001, 0x00000000); disable_clk_src(priv, src1); } else { nv_mask(priv, src1, 0x003f3141, 0x00000101 | info->clk); nv_mask(priv, ctrl, 0x00000018, 0x00000018); udelay(20); nv_mask(priv, ctrl, 0x00000001, 0x00000000); nv_mask(priv, src0, 0x00000100, 0x00000000); nv_mask(priv, src0, 0x00000001, 0x00000000); disable_clk_src(priv, src0); } } Loading @@ -294,6 +331,33 @@ prog_clk(struct nva3_clock_priv *priv, int clk, int idx) nv_mask(priv, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | info->clk); } static void prog_host(struct nva3_clock_priv *priv) { struct nva3_clock_info *info = &priv->eng[nv_clk_src_host]; u32 hsrc = (nv_rd32(priv, 0xc040)); switch (info->host_out) { case NVA3_HOST_277: if ((hsrc & 0x30000000) == 0) { nv_wr32(priv, 0xc040, hsrc | 0x20000000); disable_clk_src(priv, 0x4194); } break; case NVA3_HOST_CLK: prog_clk(priv, 0x1d, nv_clk_src_host); if ((hsrc & 0x30000000) >= 0x20000000) { nv_wr32(priv, 0xc040, hsrc & ~0x30000000); } break; default: break; } /* This seems to be a clock gating factor on idle, always set to 64 */ nv_wr32(priv, 0xc044, 0x3e); } static int nva3_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) { Loading @@ -303,7 +367,8 @@ nva3_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) if ((ret = calc_clk(priv, cstate, 0x10, 0x4200, nv_clk_src_core)) || (ret = calc_clk(priv, cstate, 0x11, 0x4220, nv_clk_src_shader)) || (ret = calc_clk(priv, cstate, 0x20, 0x0000, nv_clk_src_disp)) || (ret = calc_clk(priv, cstate, 0x21, 0x0000, nv_clk_src_vdec))) (ret = calc_clk(priv, cstate, 0x21, 0x0000, nv_clk_src_vdec)) || (ret = calc_host(priv, cstate))) return ret; return 0; Loading @@ -317,6 +382,7 @@ nva3_clock_prog(struct nouveau_clock *clk) prog_pll(priv, 0x01, 0x004220, nv_clk_src_shader); prog_clk(priv, 0x20, nv_clk_src_disp); prog_clk(priv, 0x21, nv_clk_src_vdec); prog_host(priv); return 0; } Loading @@ -328,12 +394,12 @@ nva3_clock_tidy(struct nouveau_clock *clk) static struct nouveau_clocks nva3_domain[] = { { nv_clk_src_crystal, 0xff }, { nv_clk_src_href , 0xff }, { nv_clk_src_core , 0x00, 0, "core", 1000 }, { nv_clk_src_shader , 0x01, 0, "shader", 1000 }, { nv_clk_src_mem , 0x02, 0, "memory", 1000 }, { nv_clk_src_vdec , 0x03 }, { nv_clk_src_disp , 0x04 }, { nv_clk_src_host , 0x05 }, { nv_clk_src_max } }; Loading drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h +4 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,10 @@ struct nva3_clock_info { u32 clk; u32 pll; enum { NVA3_HOST_277, NVA3_HOST_CLK, } host_out; }; int nva3_pll_info(struct nouveau_clock *, int, u32, u32, Loading Loading
drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +74 −8 Original line number Diff line number Diff line Loading @@ -136,12 +136,11 @@ static int nva3_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) { struct nva3_clock_priv *priv = (void *)clk; u32 hsrc; switch (src) { case nv_clk_src_crystal: return nv_device(priv)->crystal; case nv_clk_src_href: return 100000; case nv_clk_src_core: return read_pll(priv, 0x00, 0x4200); case nv_clk_src_shader: Loading @@ -154,6 +153,18 @@ nva3_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) return read_clk(priv, 0x21, false); case nv_clk_src_daemon: return read_clk(priv, 0x25, false); case nv_clk_src_host: hsrc = (nv_rd32(priv, 0xc040) & 0x30000000) >> 28; switch (hsrc) { case 0: return read_clk(priv, 0x1d, false); case 2: case 3: return 277000; default: nv_error(clk, "unknown HOST clock source %d\n", hsrc); return -EINVAL; } default: nv_error(clk, "invalid clock source %d\n", src); return -EINVAL; Loading Loading @@ -258,6 +269,34 @@ calc_clk(struct nva3_clock_priv *priv, struct nouveau_cstate *cstate, return ret; } static int calc_host(struct nva3_clock_priv *priv, struct nouveau_cstate *cstate) { int ret = 0; u32 kHz = cstate->domain[nv_clk_src_host]; struct nva3_clock_info *info = &priv->eng[nv_clk_src_host]; if (kHz == 277000) { info->clk = 0; info->host_out = NVA3_HOST_277; return 0; } info->host_out = NVA3_HOST_CLK; ret = nva3_clk_info(&priv->base, 0x1d, kHz, info); if (ret >= 0) return 0; return ret; } static void disable_clk_src(struct nva3_clock_priv *priv, u32 src) { nv_mask(priv, src, 0x00000100, 0x00000000); nv_mask(priv, src, 0x00000001, 0x00000000); } static void prog_pll(struct nva3_clock_priv *priv, int clk, u32 pll, int idx) { Loading @@ -275,15 +314,13 @@ prog_pll(struct nva3_clock_priv *priv, int clk, u32 pll, int idx) nv_wait(priv, ctrl, 0x00020000, 0x00020000); nv_mask(priv, ctrl, 0x00000010, 0x00000010); nv_mask(priv, ctrl, 0x00000008, 0x00000000); nv_mask(priv, src1, 0x00000100, 0x00000000); nv_mask(priv, src1, 0x00000001, 0x00000000); disable_clk_src(priv, src1); } else { nv_mask(priv, src1, 0x003f3141, 0x00000101 | info->clk); nv_mask(priv, ctrl, 0x00000018, 0x00000018); udelay(20); nv_mask(priv, ctrl, 0x00000001, 0x00000000); nv_mask(priv, src0, 0x00000100, 0x00000000); nv_mask(priv, src0, 0x00000001, 0x00000000); disable_clk_src(priv, src0); } } Loading @@ -294,6 +331,33 @@ prog_clk(struct nva3_clock_priv *priv, int clk, int idx) nv_mask(priv, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | info->clk); } static void prog_host(struct nva3_clock_priv *priv) { struct nva3_clock_info *info = &priv->eng[nv_clk_src_host]; u32 hsrc = (nv_rd32(priv, 0xc040)); switch (info->host_out) { case NVA3_HOST_277: if ((hsrc & 0x30000000) == 0) { nv_wr32(priv, 0xc040, hsrc | 0x20000000); disable_clk_src(priv, 0x4194); } break; case NVA3_HOST_CLK: prog_clk(priv, 0x1d, nv_clk_src_host); if ((hsrc & 0x30000000) >= 0x20000000) { nv_wr32(priv, 0xc040, hsrc & ~0x30000000); } break; default: break; } /* This seems to be a clock gating factor on idle, always set to 64 */ nv_wr32(priv, 0xc044, 0x3e); } static int nva3_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) { Loading @@ -303,7 +367,8 @@ nva3_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) if ((ret = calc_clk(priv, cstate, 0x10, 0x4200, nv_clk_src_core)) || (ret = calc_clk(priv, cstate, 0x11, 0x4220, nv_clk_src_shader)) || (ret = calc_clk(priv, cstate, 0x20, 0x0000, nv_clk_src_disp)) || (ret = calc_clk(priv, cstate, 0x21, 0x0000, nv_clk_src_vdec))) (ret = calc_clk(priv, cstate, 0x21, 0x0000, nv_clk_src_vdec)) || (ret = calc_host(priv, cstate))) return ret; return 0; Loading @@ -317,6 +382,7 @@ nva3_clock_prog(struct nouveau_clock *clk) prog_pll(priv, 0x01, 0x004220, nv_clk_src_shader); prog_clk(priv, 0x20, nv_clk_src_disp); prog_clk(priv, 0x21, nv_clk_src_vdec); prog_host(priv); return 0; } Loading @@ -328,12 +394,12 @@ nva3_clock_tidy(struct nouveau_clock *clk) static struct nouveau_clocks nva3_domain[] = { { nv_clk_src_crystal, 0xff }, { nv_clk_src_href , 0xff }, { nv_clk_src_core , 0x00, 0, "core", 1000 }, { nv_clk_src_shader , 0x01, 0, "shader", 1000 }, { nv_clk_src_mem , 0x02, 0, "memory", 1000 }, { nv_clk_src_vdec , 0x03 }, { nv_clk_src_disp , 0x04 }, { nv_clk_src_host , 0x05 }, { nv_clk_src_max } }; Loading
drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h +4 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,10 @@ struct nva3_clock_info { u32 clk; u32 pll; enum { NVA3_HOST_277, NVA3_HOST_CLK, } host_out; }; int nva3_pll_info(struct nouveau_clock *, int, u32, u32, Loading