From 11278b0956f0e19b07cc23524dd5c45755a48c5d Mon Sep 17 00:00:00 2001 From: Alex Frid Date: Tue, 11 Apr 2017 19:40:39 -0700 Subject: gpu: nvgpu: Add support for GM20B GPC PLL C1 rev Separated parameters for GM20B GPC PLL revisions B1 (default), and C1 (new, not characterized, yet). For now, used C1 spec settings. Skipped PL divider glitch WAR, since revision C1 is glitchless. Bug 1851797 Bug 1867980 Change-Id: I12dc101d002a41230e9323c47af234f6bae8e034 Signed-off-by: Alex Frid Reviewed-on: http://git-master/r/1461680 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/gm20b/clk_gm20b.c | 43 ++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/nvgpu/gm20b/clk_gm20b.c') diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c index eb8f31e8..aaea080a 100644 --- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c @@ -52,7 +52,7 @@ #define DVFS_SAFE_MARGIN 10 /* 10% */ static unsigned long dvfs_safe_max_freq; -static struct pll_parms gpc_pll_params = { +static struct pll_parms gpc_pll_params_b1 = { 128000, 2600000, /* freq */ 1300000, 2600000, /* vco */ 12000, 38400, /* u */ @@ -67,6 +67,23 @@ static struct pll_parms gpc_pll_params = { 5, /* IDDQ mode exit delay */ }; +static struct pll_parms gpc_pll_params_c1 = { + 128000, 2600000, /* freq */ + 1300000, 2600000, /* vco */ + 19200, 38400, /* u */ + 1, 255, /* M */ + 8, 255, /* N */ + 1, 31, /* PL */ + 0, 0, /* DFS_COEFF */ + 0, 0, /* ADC char coeff - to be read from fuses */ + 0x7 << 3, /* vco control in NA mode */ + 500, /* Locking and ramping timeout */ + 40, /* Lock delay in NA mode */ + 5, /* IDDQ mode exit delay */ +}; + +static struct pll_parms gpc_pll_params; + #ifdef CONFIG_DEBUG_FS static int clk_gm20b_debugfs_init(struct gk20a *g); #endif @@ -110,11 +127,11 @@ static inline u32 div_to_pl(u32 div) * Post divider tarnsition is glitchless only if there is common "1" in binary * representation of old and new settings. */ -static u32 get_interim_pldiv(u32 old_pl, u32 new_pl) +static u32 get_interim_pldiv(struct gk20a *g, u32 old_pl, u32 new_pl) { u32 pl; - if (old_pl & new_pl) + if ((g->clk.gpc_pll.id == GM20B_GPC_PLL_C1) || (old_pl & new_pl)) return 0; pl = old_pl | BIT(ffs(new_pl) - 1); /* pl never 0 */ @@ -891,7 +908,7 @@ static int clk_program_gpc_pll(struct gk20a *g, struct pll *gpll_new, coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r()); if (pldiv_only) { /* Insert interim PLDIV state if necessary */ - u32 interim_pl = get_interim_pldiv(gpll_new->PL, gpll.PL); + u32 interim_pl = get_interim_pldiv(g, gpll_new->PL, gpll.PL); if (interim_pl) { coeff = set_field(coeff, trim_sys_gpcpll_coeff_pldiv_m(), @@ -1135,6 +1152,9 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g) return 0; } + gpc_pll_params = (clk->gpc_pll.id == GM20B_GPC_PLL_C1) ? + gpc_pll_params_c1 : gpc_pll_params_b1; + if (!gk20a_clk_get(g)) { err = -EINVAL; goto fail; @@ -1159,7 +1179,6 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g) goto fail; } - clk->gpc_pll.id = GK20A_GPC_PLL; clk->gpc_pll.clk_in = clk_get_rate(ref) / KHZ; if (clk->gpc_pll.clk_in == 0) { nvgpu_err(g, "GPCPLL reference clock is zero"); @@ -1201,9 +1220,11 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g) clk->sw_ready = true; gk20a_dbg_fn("done"); - dev_info(dev_from_gk20a(g), "GPCPLL initial settings:%s M=%u, N=%u, P=%u", + nvgpu_info(g, + "GPCPLL initial settings:%s M=%u, N=%u, P=%u (id = %u)", clk->gpc_pll.mode == GPC_PLL_MODE_DVFS ? " NA mode," : "", - clk->gpc_pll.M, clk->gpc_pll.N, clk->gpc_pll.PL); + clk->gpc_pll.M, clk->gpc_pll.N, clk->gpc_pll.PL, + clk->gpc_pll.id); return 0; fail: @@ -1623,7 +1644,7 @@ DEFINE_SIMPLE_ATTRIBUTE(rate_fops, rate_get, rate_set, "%llu\n"); static int pll_reg_show(struct seq_file *s, void *data) { struct gk20a *g = s->private; - u32 reg, m, n, pl, f; + u32 reg, m, n, pl, f, d, dmax, doffs; nvgpu_mutex_acquire(&g->clk.clk_mutex); if (!g->clk.clk_hw_on) { @@ -1651,6 +1672,12 @@ static int pll_reg_show(struct seq_file *s, void *data) f = g->clk.gpc_pll.clk_in * n / (m * pl_to_div(pl)); seq_printf(s, "coef = 0x%x : m = %u : n = %u : pl = %u", reg, m, n, pl); seq_printf(s, " : pll_f(gpu_f) = %u(%u) kHz\n", f, f/2); + reg = gk20a_readl(g, trim_sys_gpcpll_dvfs0_r()); + d = trim_sys_gpcpll_dvfs0_dfs_coeff_v(reg); + dmax = trim_sys_gpcpll_dvfs0_dfs_det_max_v(reg); + doffs = trim_sys_gpcpll_dvfs0_dfs_dc_offset_v(reg); + seq_printf(s, "dvfs0 = 0x%x : d = %u : dmax = %u : doffs = %u\n", + reg, d, dmax, doffs); nvgpu_mutex_release(&g->clk.clk_mutex); return 0; } -- cgit v1.2.2