summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2017-04-11 22:40:39 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-04-20 19:14:27 -0400
commit11278b0956f0e19b07cc23524dd5c45755a48c5d (patch)
tree3d436a7c8fab54fdb1e67510309e299a023cbe30 /drivers/gpu/nvgpu/gm20b/clk_gm20b.c
parent7ff9bb2c71186bd721b31f6c74f4010d723ca816 (diff)
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 <afrid@nvidia.com> Reviewed-on: http://git-master/r/1461680 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gm20b/clk_gm20b.c')
-rw-r--r--drivers/gpu/nvgpu/gm20b/clk_gm20b.c43
1 files changed, 35 insertions, 8 deletions
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 @@
52#define DVFS_SAFE_MARGIN 10 /* 10% */ 52#define DVFS_SAFE_MARGIN 10 /* 10% */
53static unsigned long dvfs_safe_max_freq; 53static unsigned long dvfs_safe_max_freq;
54 54
55static struct pll_parms gpc_pll_params = { 55static struct pll_parms gpc_pll_params_b1 = {
56 128000, 2600000, /* freq */ 56 128000, 2600000, /* freq */
57 1300000, 2600000, /* vco */ 57 1300000, 2600000, /* vco */
58 12000, 38400, /* u */ 58 12000, 38400, /* u */
@@ -67,6 +67,23 @@ static struct pll_parms gpc_pll_params = {
67 5, /* IDDQ mode exit delay */ 67 5, /* IDDQ mode exit delay */
68}; 68};
69 69
70static struct pll_parms gpc_pll_params_c1 = {
71 128000, 2600000, /* freq */
72 1300000, 2600000, /* vco */
73 19200, 38400, /* u */
74 1, 255, /* M */
75 8, 255, /* N */
76 1, 31, /* PL */
77 0, 0, /* DFS_COEFF */
78 0, 0, /* ADC char coeff - to be read from fuses */
79 0x7 << 3, /* vco control in NA mode */
80 500, /* Locking and ramping timeout */
81 40, /* Lock delay in NA mode */
82 5, /* IDDQ mode exit delay */
83};
84
85static struct pll_parms gpc_pll_params;
86
70#ifdef CONFIG_DEBUG_FS 87#ifdef CONFIG_DEBUG_FS
71static int clk_gm20b_debugfs_init(struct gk20a *g); 88static int clk_gm20b_debugfs_init(struct gk20a *g);
72#endif 89#endif
@@ -110,11 +127,11 @@ static inline u32 div_to_pl(u32 div)
110 * Post divider tarnsition is glitchless only if there is common "1" in binary 127 * Post divider tarnsition is glitchless only if there is common "1" in binary
111 * representation of old and new settings. 128 * representation of old and new settings.
112 */ 129 */
113static u32 get_interim_pldiv(u32 old_pl, u32 new_pl) 130static u32 get_interim_pldiv(struct gk20a *g, u32 old_pl, u32 new_pl)
114{ 131{
115 u32 pl; 132 u32 pl;
116 133
117 if (old_pl & new_pl) 134 if ((g->clk.gpc_pll.id == GM20B_GPC_PLL_C1) || (old_pl & new_pl))
118 return 0; 135 return 0;
119 136
120 pl = old_pl | BIT(ffs(new_pl) - 1); /* pl never 0 */ 137 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,
891 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r()); 908 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
892 if (pldiv_only) { 909 if (pldiv_only) {
893 /* Insert interim PLDIV state if necessary */ 910 /* Insert interim PLDIV state if necessary */
894 u32 interim_pl = get_interim_pldiv(gpll_new->PL, gpll.PL); 911 u32 interim_pl = get_interim_pldiv(g, gpll_new->PL, gpll.PL);
895 if (interim_pl) { 912 if (interim_pl) {
896 coeff = set_field(coeff, 913 coeff = set_field(coeff,
897 trim_sys_gpcpll_coeff_pldiv_m(), 914 trim_sys_gpcpll_coeff_pldiv_m(),
@@ -1135,6 +1152,9 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1135 return 0; 1152 return 0;
1136 } 1153 }
1137 1154
1155 gpc_pll_params = (clk->gpc_pll.id == GM20B_GPC_PLL_C1) ?
1156 gpc_pll_params_c1 : gpc_pll_params_b1;
1157
1138 if (!gk20a_clk_get(g)) { 1158 if (!gk20a_clk_get(g)) {
1139 err = -EINVAL; 1159 err = -EINVAL;
1140 goto fail; 1160 goto fail;
@@ -1159,7 +1179,6 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1159 goto fail; 1179 goto fail;
1160 } 1180 }
1161 1181
1162 clk->gpc_pll.id = GK20A_GPC_PLL;
1163 clk->gpc_pll.clk_in = clk_get_rate(ref) / KHZ; 1182 clk->gpc_pll.clk_in = clk_get_rate(ref) / KHZ;
1164 if (clk->gpc_pll.clk_in == 0) { 1183 if (clk->gpc_pll.clk_in == 0) {
1165 nvgpu_err(g, "GPCPLL reference clock is zero"); 1184 nvgpu_err(g, "GPCPLL reference clock is zero");
@@ -1201,9 +1220,11 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1201 clk->sw_ready = true; 1220 clk->sw_ready = true;
1202 1221
1203 gk20a_dbg_fn("done"); 1222 gk20a_dbg_fn("done");
1204 dev_info(dev_from_gk20a(g), "GPCPLL initial settings:%s M=%u, N=%u, P=%u", 1223 nvgpu_info(g,
1224 "GPCPLL initial settings:%s M=%u, N=%u, P=%u (id = %u)",
1205 clk->gpc_pll.mode == GPC_PLL_MODE_DVFS ? " NA mode," : "", 1225 clk->gpc_pll.mode == GPC_PLL_MODE_DVFS ? " NA mode," : "",
1206 clk->gpc_pll.M, clk->gpc_pll.N, clk->gpc_pll.PL); 1226 clk->gpc_pll.M, clk->gpc_pll.N, clk->gpc_pll.PL,
1227 clk->gpc_pll.id);
1207 return 0; 1228 return 0;
1208 1229
1209fail: 1230fail:
@@ -1623,7 +1644,7 @@ DEFINE_SIMPLE_ATTRIBUTE(rate_fops, rate_get, rate_set, "%llu\n");
1623static int pll_reg_show(struct seq_file *s, void *data) 1644static int pll_reg_show(struct seq_file *s, void *data)
1624{ 1645{
1625 struct gk20a *g = s->private; 1646 struct gk20a *g = s->private;
1626 u32 reg, m, n, pl, f; 1647 u32 reg, m, n, pl, f, d, dmax, doffs;
1627 1648
1628 nvgpu_mutex_acquire(&g->clk.clk_mutex); 1649 nvgpu_mutex_acquire(&g->clk.clk_mutex);
1629 if (!g->clk.clk_hw_on) { 1650 if (!g->clk.clk_hw_on) {
@@ -1651,6 +1672,12 @@ static int pll_reg_show(struct seq_file *s, void *data)
1651 f = g->clk.gpc_pll.clk_in * n / (m * pl_to_div(pl)); 1672 f = g->clk.gpc_pll.clk_in * n / (m * pl_to_div(pl));
1652 seq_printf(s, "coef = 0x%x : m = %u : n = %u : pl = %u", reg, m, n, pl); 1673 seq_printf(s, "coef = 0x%x : m = %u : n = %u : pl = %u", reg, m, n, pl);
1653 seq_printf(s, " : pll_f(gpu_f) = %u(%u) kHz\n", f, f/2); 1674 seq_printf(s, " : pll_f(gpu_f) = %u(%u) kHz\n", f, f/2);
1675 reg = gk20a_readl(g, trim_sys_gpcpll_dvfs0_r());
1676 d = trim_sys_gpcpll_dvfs0_dfs_coeff_v(reg);
1677 dmax = trim_sys_gpcpll_dvfs0_dfs_det_max_v(reg);
1678 doffs = trim_sys_gpcpll_dvfs0_dfs_dc_offset_v(reg);
1679 seq_printf(s, "dvfs0 = 0x%x : d = %u : dmax = %u : doffs = %u\n",
1680 reg, d, dmax, doffs);
1654 nvgpu_mutex_release(&g->clk.clk_mutex); 1681 nvgpu_mutex_release(&g->clk.clk_mutex);
1655 return 0; 1682 return 0;
1656} 1683}