summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
diff options
context:
space:
mode:
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}