summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu
diff options
context:
space:
mode:
authorVijayakumar <vsubbu@nvidia.com>2016-09-16 09:26:22 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:56:50 -0500
commitc7fbd76e7101b7dedc8c0f04437288d1d6b78adc (patch)
tree6d1ab41af52a481ddeb148307a69113582569edd /drivers/gpu/nvgpu
parent3c351f5bb2d04c1f70c72f3f2fd758bbb340877c (diff)
gpu: nvgpu: create function to program coreclk
JIRA DNVGPU-123 now a function can be called with GPC2CLK value It will take care calculating slave clock values and calling VF inject to program clock Made programming of boot clock code to use this newly created function. Change-Id: I74de7e9d98e379e94175ed2d9745ce3ab6c70691 Signed-off-by: Vijayakumar <vsubbu@nvidia.com> Reviewed-on: http://git-master/r/1221976 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/1235056
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r--drivers/gpu/nvgpu/clk/clk.c229
-rw-r--r--drivers/gpu/nvgpu/clk/clk.h24
-rw-r--r--drivers/gpu/nvgpu/clk/clk_domain.c69
-rw-r--r--drivers/gpu/nvgpu/clk/clk_domain.h7
-rw-r--r--drivers/gpu/nvgpu/clk/clk_prog.c55
-rw-r--r--drivers/gpu/nvgpu/clk/clk_prog.h6
-rw-r--r--drivers/gpu/nvgpu/pstate/pstate.c4
7 files changed, 358 insertions, 36 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c
index 7ee4f283..918cd43c 100644
--- a/drivers/gpu/nvgpu/clk/clk.c
+++ b/drivers/gpu/nvgpu/clk/clk.c
@@ -104,7 +104,7 @@ done:
104 return status; 104 return status;
105} 105}
106 106
107u32 clk_pmu_vf_inject(struct gk20a *g) 107static u32 clk_pmu_vf_inject(struct gk20a *g, struct set_fll_clk *setfllclk)
108{ 108{
109 struct pmu_cmd cmd; 109 struct pmu_cmd cmd;
110 struct pmu_msg msg; 110 struct pmu_msg msg;
@@ -115,35 +115,48 @@ u32 clk_pmu_vf_inject(struct gk20a *g)
115 struct clkrpc_pmucmdhandler_params handler = {0}; 115 struct clkrpc_pmucmdhandler_params handler = {0};
116 struct nv_pmu_clk_vf_change_inject *vfchange; 116 struct nv_pmu_clk_vf_change_inject *vfchange;
117 117
118 if ((setfllclk->gpc2clkmhz == 0) || (setfllclk->xbar2clkmhz == 0) ||
119 (setfllclk->sys2clkmhz == 0) || (setfllclk->voltuv == 0))
120 return -EINVAL;
121
122 if ((setfllclk->target_regime_id_gpc > CTRL_CLK_FLL_REGIME_ID_FR) ||
123 (setfllclk->target_regime_id_sys > CTRL_CLK_FLL_REGIME_ID_FR) ||
124 (setfllclk->target_regime_id_xbar > CTRL_CLK_FLL_REGIME_ID_FR))
125 return -EINVAL;
126
118 rpccall.function = NV_PMU_CLK_RPC_ID_CLK_VF_CHANGE_INJECT; 127 rpccall.function = NV_PMU_CLK_RPC_ID_CLK_VF_CHANGE_INJECT;
119 vfchange = &rpccall.params.clk_vf_change_inject; 128 vfchange = &rpccall.params.clk_vf_change_inject;
120 vfchange->flags = 0; 129 vfchange->flags = 0;
121 vfchange->clk_list.num_domains = 3; 130 vfchange->clk_list.num_domains = 3;
122 vfchange->clk_list.clk_domains[0].clk_domain = CTRL_CLK_DOMAIN_GPC2CLK; 131 vfchange->clk_list.clk_domains[0].clk_domain = CTRL_CLK_DOMAIN_GPC2CLK;
123 vfchange->clk_list.clk_domains[0].clk_freq_khz = 2581 * 1000; 132 vfchange->clk_list.clk_domains[0].clk_freq_khz =
133 setfllclk->gpc2clkmhz * 1000;
124 vfchange->clk_list.clk_domains[0].clk_flags = 0; 134 vfchange->clk_list.clk_domains[0].clk_flags = 0;
125 vfchange->clk_list.clk_domains[0].current_regime_id = 135 vfchange->clk_list.clk_domains[0].current_regime_id =
126 CTRL_CLK_FLL_REGIME_ID_FFR; 136 setfllclk->current_regime_id_gpc;
127 vfchange->clk_list.clk_domains[0].target_regime_id = 137 vfchange->clk_list.clk_domains[0].target_regime_id =
128 CTRL_CLK_FLL_REGIME_ID_FR; 138 setfllclk->target_regime_id_gpc;
129 vfchange->clk_list.clk_domains[1].clk_domain = CTRL_CLK_DOMAIN_XBAR2CLK; 139 vfchange->clk_list.clk_domains[1].clk_domain = CTRL_CLK_DOMAIN_XBAR2CLK;
130 vfchange->clk_list.clk_domains[1].clk_freq_khz = 2505 * 1000; 140 vfchange->clk_list.clk_domains[1].clk_freq_khz =
141 setfllclk->xbar2clkmhz * 1000;
131 vfchange->clk_list.clk_domains[1].clk_flags = 0; 142 vfchange->clk_list.clk_domains[1].clk_flags = 0;
132 vfchange->clk_list.clk_domains[1].current_regime_id = 143 vfchange->clk_list.clk_domains[1].current_regime_id =
133 CTRL_CLK_FLL_REGIME_ID_FFR; 144 setfllclk->current_regime_id_xbar;
134 vfchange->clk_list.clk_domains[1].target_regime_id = 145 vfchange->clk_list.clk_domains[1].target_regime_id =
135 CTRL_CLK_FLL_REGIME_ID_FR; 146 setfllclk->target_regime_id_xbar;
136 vfchange->clk_list.clk_domains[2].clk_domain = CTRL_CLK_DOMAIN_SYS2CLK; 147 vfchange->clk_list.clk_domains[2].clk_domain = CTRL_CLK_DOMAIN_SYS2CLK;
137 vfchange->clk_list.clk_domains[2].clk_freq_khz = 2328 * 1000; 148 vfchange->clk_list.clk_domains[2].clk_freq_khz =
149 setfllclk->sys2clkmhz * 1000;
138 vfchange->clk_list.clk_domains[2].clk_flags = 0; 150 vfchange->clk_list.clk_domains[2].clk_flags = 0;
139 vfchange->clk_list.clk_domains[2].current_regime_id = 151 vfchange->clk_list.clk_domains[2].current_regime_id =
140 CTRL_CLK_FLL_REGIME_ID_FFR; 152 setfllclk->current_regime_id_sys;
141 vfchange->clk_list.clk_domains[2].target_regime_id = 153 vfchange->clk_list.clk_domains[2].target_regime_id =
142 CTRL_CLK_FLL_REGIME_ID_FR; 154 setfllclk->target_regime_id_sys;
143 vfchange->volt_list.num_rails = 1; 155 vfchange->volt_list.num_rails = 1;
144 vfchange->volt_list.rails[0].volt_domain = CTRL_VOLT_DOMAIN_LOGIC; 156 vfchange->volt_list.rails[0].volt_domain = CTRL_VOLT_DOMAIN_LOGIC;
145 vfchange->volt_list.rails[0].voltage_uv = 825000; 157 vfchange->volt_list.rails[0].voltage_uv = setfllclk->voltuv;
146 vfchange->volt_list.rails[0].voltage_min_noise_unaware_uv = 825000; 158 vfchange->volt_list.rails[0].voltage_min_noise_unaware_uv =
159 setfllclk->voltuv;
147 160
148 cmd.hdr.unit_id = PMU_UNIT_CLK; 161 cmd.hdr.unit_id = PMU_UNIT_CLK;
149 cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) + 162 cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) +
@@ -189,6 +202,198 @@ done:
189 return status; 202 return status;
190} 203}
191 204
205static u32 find_regime_id(struct gk20a *g, u32 domain, u16 clkmhz)
206{
207 struct fll_device *pflldev;
208 u8 j;
209 struct clk_pmupstate *pclk = &g->clk_pmu;
210
211 BOARDOBJGRP_FOR_EACH(&(pclk->avfs_fllobjs.super.super),
212 struct fll_device *, pflldev, j) {
213 if (pflldev->clk_domain == domain) {
214 if (pflldev->regime_desc.fixed_freq_regime_limit_mhz >=
215 clkmhz)
216 return CTRL_CLK_FLL_REGIME_ID_FR;
217 else
218 return CTRL_CLK_FLL_REGIME_ID_FFR;
219 }
220 }
221 return CTRL_CLK_FLL_REGIME_ID_INVALID;
222}
223
224static int set_regime_id(struct gk20a *g, u32 domain, u32 regimeid)
225{
226 struct fll_device *pflldev;
227 u8 j;
228 struct clk_pmupstate *pclk = &g->clk_pmu;
229
230 BOARDOBJGRP_FOR_EACH(&(pclk->avfs_fllobjs.super.super),
231 struct fll_device *, pflldev, j) {
232 if (pflldev->clk_domain == domain) {
233 pflldev->regime_desc.regime_id = regimeid;
234 return 0;
235 }
236 }
237 return -EINVAL;
238}
239
240static int get_regime_id(struct gk20a *g, u32 domain, u32 *regimeid)
241{
242 struct fll_device *pflldev;
243 u8 j;
244 struct clk_pmupstate *pclk = &g->clk_pmu;
245
246 BOARDOBJGRP_FOR_EACH(&(pclk->avfs_fllobjs.super.super),
247 struct fll_device *, pflldev, j) {
248 if (pflldev->clk_domain == domain) {
249 *regimeid = pflldev->regime_desc.regime_id;
250 return 0;
251 }
252 }
253 return -EINVAL;
254}
255
256int clk_program_fllclks(struct gk20a *g, struct change_fll_clk *fllclk)
257{
258 int status = -EINVAL;
259 struct clk_domain *pdomain;
260 u8 i;
261 struct clk_pmupstate *pclk = &g->clk_pmu;
262 u16 clkmhz = 0;
263 struct clk_domain_3x_master *p3xmaster;
264 struct clk_domain_3x_slave *p3xslave;
265 unsigned long slaveidxmask;
266 struct set_fll_clk setfllclk;
267 bool foundxbar2clk = false;
268 bool foundsys2clk = false;
269
270 memset(&setfllclk, 0, sizeof(setfllclk));
271 if (fllclk->api_clk_domain != CTRL_CLK_DOMAIN_GPC2CLK)
272 return -EINVAL;
273 if (fllclk->voltuv == 0)
274 return -EINVAL;
275 if (fllclk->clkmhz == 0)
276 return -EINVAL;
277
278 mutex_lock(&pclk->changeclkmutex);
279
280 setfllclk.voltuv = fllclk->voltuv;
281 setfllclk.gpc2clkmhz = fllclk->clkmhz;
282
283 BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super),
284 struct clk_domain *, pdomain, i) {
285
286 if (pdomain->api_domain == fllclk->api_clk_domain) {
287
288 if (!pdomain->super.implements(g, &pdomain->super,
289 CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) {
290 status = -EINVAL;
291 goto done;
292 }
293 p3xmaster = (struct clk_domain_3x_master *)pdomain;
294 slaveidxmask = p3xmaster->slave_idxs_mask;
295 for_each_set_bit(i, &slaveidxmask, 32) {
296 p3xslave = (struct clk_domain_3x_slave *)
297 CLK_CLK_DOMAIN_GET(pclk, i);
298 if ((p3xslave->super.super.super.api_domain !=
299 CTRL_CLK_DOMAIN_XBAR2CLK) &&
300 (p3xslave->super.super.super.api_domain !=
301 CTRL_CLK_DOMAIN_SYS2CLK))
302 continue;
303 clkmhz = 0;
304 status = p3xslave->clkdomainclkgetslaveclk(g,
305 pclk,
306 (struct clk_domain *)p3xslave,
307 &clkmhz,
308 fllclk->clkmhz);
309 if (status) {
310 status = -EINVAL;
311 goto done;
312 }
313 if (p3xslave->super.super.super.api_domain ==
314 CTRL_CLK_DOMAIN_XBAR2CLK) {
315 setfllclk.xbar2clkmhz = clkmhz;
316 foundxbar2clk = true;
317 }
318 if (p3xslave->super.super.super.api_domain ==
319 CTRL_CLK_DOMAIN_SYS2CLK) {
320 setfllclk.sys2clkmhz = clkmhz;
321 foundsys2clk = true;
322 }
323 }
324 }
325 }
326 if (!(foundxbar2clk && foundsys2clk)) {
327 status = -EINVAL;
328 goto done;
329 }
330 /*set regime ids */
331 status = get_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK,
332 &setfllclk.current_regime_id_gpc);
333 if (status)
334 goto done;
335
336 setfllclk.target_regime_id_gpc = find_regime_id(g,
337 CTRL_CLK_DOMAIN_GPC2CLK, setfllclk.gpc2clkmhz);
338
339 status = get_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK,
340 &setfllclk.current_regime_id_sys);
341 if (status)
342 goto done;
343
344 setfllclk.target_regime_id_sys = find_regime_id(g,
345 CTRL_CLK_DOMAIN_SYS2CLK, setfllclk.sys2clkmhz);
346
347 status = get_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK,
348 &setfllclk.current_regime_id_xbar);
349 if (status)
350 goto done;
351
352 setfllclk.target_regime_id_xbar = find_regime_id(g,
353 CTRL_CLK_DOMAIN_XBAR2CLK, setfllclk.xbar2clkmhz);
354
355 status = clk_pmu_vf_inject(g, &setfllclk);
356
357 if (status)
358 gk20a_err(dev_from_gk20a(g),
359 "vf inject to change clk failed");
360
361 /* save regime ids */
362 status = set_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK,
363 setfllclk.target_regime_id_xbar);
364 if (status)
365 goto done;
366
367 status = set_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK,
368 setfllclk.target_regime_id_gpc);
369 if (status)
370 goto done;
371
372 status = set_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK,
373 setfllclk.target_regime_id_sys);
374 if (status)
375 goto done;
376done:
377 mutex_unlock(&pclk->changeclkmutex);
378 return status;
379}
380
381int clk_set_boot_fll_clk(struct gk20a *g)
382{
383 int status;
384 struct change_fll_clk bootfllclk;
385
386 mutex_init(&g->clk_pmu.changeclkmutex);
387
388 bootfllclk.api_clk_domain = CTRL_CLK_DOMAIN_GPC2CLK;
389 bootfllclk.clkmhz = 2581;
390 bootfllclk.voltuv = 825000;
391 status = clk_program_fllclks(g, &bootfllclk);
392 if (status)
393 gk20a_err(dev_from_gk20a(g), "attemp to set boot clk failed");
394 return status;
395}
396
192u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain) 397u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain)
193{ 398{
194 u32 status = -EINVAL; 399 u32 status = -EINVAL;
diff --git a/drivers/gpu/nvgpu/clk/clk.h b/drivers/gpu/nvgpu/clk/clk.h
index 1f25fa4e..e54af521 100644
--- a/drivers/gpu/nvgpu/clk/clk.h
+++ b/drivers/gpu/nvgpu/clk/clk.h
@@ -35,6 +35,7 @@ struct clk_pmupstate {
35 struct clk_progs clk_progobjs; 35 struct clk_progs clk_progobjs;
36 struct clk_vf_points clk_vf_pointobjs; 36 struct clk_vf_points clk_vf_pointobjs;
37 struct clk_mclk_state clk_mclk; 37 struct clk_mclk_state clk_mclk;
38 struct mutex changeclkmutex;
38}; 39};
39 40
40struct clockentry { 41struct clockentry {
@@ -44,6 +45,25 @@ struct clockentry {
44 u32 api_clk_domain; 45 u32 api_clk_domain;
45}; 46};
46 47
48struct change_fll_clk {
49 u32 api_clk_domain;
50 u16 clkmhz;
51 u32 voltuv;
52};
53
54struct set_fll_clk {
55 u32 voltuv;
56 u16 gpc2clkmhz;
57 u32 current_regime_id_gpc;
58 u32 target_regime_id_gpc;
59 u16 sys2clkmhz;
60 u32 current_regime_id_sys;
61 u32 target_regime_id_sys;
62 u16 xbar2clkmhz;
63 u32 current_regime_id_xbar;
64 u32 target_regime_id_xbar;
65};
66
47#define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_MAX_NUMCLKS 9 67#define NV_PERF_HEADER_4X_CLOCKS_DOMAINS_MAX_NUMCLKS 9
48 68
49struct vbios_clock_domain { 69struct vbios_clock_domain {
@@ -82,7 +102,6 @@ struct vbios_clocks_table_1x_hal_clock_entry {
82#define PERF_CLK_PCIEGENCLK 12 102#define PERF_CLK_PCIEGENCLK 12
83#define PERF_CLK_NUM 13 103#define PERF_CLK_NUM 13
84 104
85u32 clk_pmu_vf_inject(struct gk20a *g);
86u32 clk_pmu_vin_load(struct gk20a *g); 105u32 clk_pmu_vin_load(struct gk20a *g);
87u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain); 106u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain);
88u32 clk_domain_get_f_or_v 107u32 clk_domain_get_f_or_v
@@ -98,5 +117,6 @@ u32 clk_domain_get_f_points(
98 u32 *fpointscount, 117 u32 *fpointscount,
99 u16 *freqpointsinmhz 118 u16 *freqpointsinmhz
100); 119);
101 120int clk_set_boot_fll_clk(struct gk20a *g);
121int clk_program_fll_clks(struct gk20a *g, struct change_fll_clk *fllclk);
102#endif 122#endif
diff --git a/drivers/gpu/nvgpu/clk/clk_domain.c b/drivers/gpu/nvgpu/clk/clk_domain.c
index f87530dc..fe3db5d6 100644
--- a/drivers/gpu/nvgpu/clk/clk_domain.c
+++ b/drivers/gpu/nvgpu/clk/clk_domain.c
@@ -422,14 +422,14 @@ static u32 clkdomainclkproglink_not_supported(struct gk20a *g,
422 return -EINVAL; 422 return -EINVAL;
423} 423}
424 424
425static u32 clkdomainvfsearch_stub( 425static int clkdomainvfsearch_stub(
426 struct gk20a *g, 426 struct gk20a *g,
427 struct clk_pmupstate *pclk, 427 struct clk_pmupstate *pclk,
428 struct clk_domain *pdomain, 428 struct clk_domain *pdomain,
429 u16 *clkmhz, 429 u16 *clkmhz,
430 u32 *voltuv, 430 u32 *voltuv,
431 u8 rail 431 u8 rail)
432) 432
433{ 433{
434 gk20a_dbg_info(""); 434 gk20a_dbg_info("");
435 return -EINVAL; 435 return -EINVAL;
@@ -441,8 +441,7 @@ static u32 clkdomaingetfpoints_stub(
441 struct clk_domain *pdomain, 441 struct clk_domain *pdomain,
442 u32 *pfpointscount, 442 u32 *pfpointscount,
443 u16 *pfreqpointsinmhz, 443 u16 *pfreqpointsinmhz,
444 u8 rail 444 u8 rail)
445)
446{ 445{
447 gk20a_dbg_info(""); 446 gk20a_dbg_info("");
448 return -EINVAL; 447 return -EINVAL;
@@ -556,17 +555,47 @@ static u32 clkdomainclkproglink_3x_prog(struct gk20a *g,
556 return status; 555 return status;
557} 556}
558 557
559static u32 clkdomainvfsearch 558static int clkdomaingetslaveclk(struct gk20a *g,
560( 559 struct clk_pmupstate *pclk,
561 struct gk20a *g, 560 struct clk_domain *pdomain,
562 struct clk_pmupstate *pclk, 561 u16 *pclkmhz,
563 struct clk_domain *pdomain, 562 u16 masterclkmhz)
564 u16 *pclkmhz,
565 u32 *pvoltuv,
566 u8 rail
567)
568{ 563{
569 u32 status = 0; 564 int status = 0;
565 struct clk_prog *pprog = NULL;
566 struct clk_prog_1x_master *pprog1xmaster = NULL;
567 u8 slaveidx;
568 struct clk_domain_3x_master *p3xmaster;
569
570 gk20a_dbg_info("");
571
572 if (pclkmhz == NULL)
573 return -EINVAL;
574
575 if (masterclkmhz == 0)
576 return -EINVAL;
577
578 slaveidx = BOARDOBJ_GET_IDX(pdomain);
579 p3xmaster = (struct clk_domain_3x_master *)
580 CLK_CLK_DOMAIN_GET(pclk,
581 ((struct clk_domain_3x_slave *)
582 pdomain)->master_idx);
583 pprog = CLK_CLK_PROG_GET(pclk, p3xmaster->super.clk_prog_idx_first);
584 pprog1xmaster = (struct clk_prog_1x_master *)pprog;
585
586 status = pprog1xmaster->getslaveclk(g, pclk, pprog1xmaster,
587 slaveidx, pclkmhz, masterclkmhz);
588 return status;
589}
590
591static int clkdomainvfsearch(struct gk20a *g,
592 struct clk_pmupstate *pclk,
593 struct clk_domain *pdomain,
594 u16 *pclkmhz,
595 u32 *pvoltuv,
596 u8 rail)
597{
598 int status = 0;
570 struct clk_domain_3x_master *p3xmaster = 599 struct clk_domain_3x_master *p3xmaster =
571 (struct clk_domain_3x_master *)pdomain; 600 (struct clk_domain_3x_master *)pdomain;
572 struct clk_prog *pprog = NULL; 601 struct clk_prog *pprog = NULL;
@@ -580,6 +609,10 @@ static u32 clkdomainvfsearch
580 u32 bestvoltuv; 609 u32 bestvoltuv;
581 610
582 gk20a_dbg_info(""); 611 gk20a_dbg_info("");
612
613 if ((pclkmhz == NULL) || (pvoltuv == NULL))
614 return -EINVAL;
615
583 if ((*pclkmhz != 0) && (*pvoltuv != 0)) 616 if ((*pclkmhz != 0) && (*pvoltuv != 0))
584 return -EINVAL; 617 return -EINVAL;
585 618
@@ -595,7 +628,6 @@ static u32 clkdomainvfsearch
595 ((struct clk_domain_3x_slave *) 628 ((struct clk_domain_3x_slave *)
596 pdomain)->master_idx); 629 pdomain)->master_idx);
597 } 630 }
598
599 /* Iterate over the set of CLK_PROGs pointed at by this domain.*/ 631 /* Iterate over the set of CLK_PROGs pointed at by this domain.*/
600 for (i = p3xmaster->super.clk_prog_idx_first; 632 for (i = p3xmaster->super.clk_prog_idx_first;
601 i <= p3xmaster->super.clk_prog_idx_last; 633 i <= p3xmaster->super.clk_prog_idx_last;
@@ -625,7 +657,7 @@ static u32 clkdomainvfsearch
625 } 657 }
626 } 658 }
627 } 659 }
628 /* clk and volt sent as zero to pring vf table */ 660 /* clk and volt sent as zero to print vf table */
629 if ((*pclkmhz == 0) && (*pvoltuv == 0)) { 661 if ((*pclkmhz == 0) && (*pvoltuv == 0)) {
630 status = 0; 662 status = 0;
631 goto done; 663 goto done;
@@ -836,6 +868,9 @@ static u32 clk_domain_construct_3x_slave(struct gk20a *g,
836 868
837 pdomain->master_idx = ptmpdomain->master_idx; 869 pdomain->master_idx = ptmpdomain->master_idx;
838 870
871 pdomain->clkdomainclkgetslaveclk =
872 clkdomaingetslaveclk;
873
839 return status; 874 return status;
840} 875}
841 876
diff --git a/drivers/gpu/nvgpu/clk/clk_domain.h b/drivers/gpu/nvgpu/clk/clk_domain.h
index eeb7c256..443e1c4c 100644
--- a/drivers/gpu/nvgpu/clk/clk_domain.h
+++ b/drivers/gpu/nvgpu/clk/clk_domain.h
@@ -30,10 +30,14 @@ u32 clk_domain_pmu_setup(struct gk20a *g);
30typedef u32 clkproglink(struct gk20a *g, struct clk_pmupstate *pclk, 30typedef u32 clkproglink(struct gk20a *g, struct clk_pmupstate *pclk,
31 struct clk_domain *pdomain); 31 struct clk_domain *pdomain);
32 32
33typedef u32 clkvfsearch(struct gk20a *g, struct clk_pmupstate *pclk, 33typedef int clkvfsearch(struct gk20a *g, struct clk_pmupstate *pclk,
34 struct clk_domain *pdomain, u16 *clkmhz, 34 struct clk_domain *pdomain, u16 *clkmhz,
35 u32 *voltuv, u8 rail); 35 u32 *voltuv, u8 rail);
36 36
37typedef int clkgetslaveclk(struct gk20a *g, struct clk_pmupstate *pclk,
38 struct clk_domain *pdomain, u16 *clkmhz,
39 u16 masterclkmhz);
40
37typedef u32 clkgetfpoints(struct gk20a *g, struct clk_pmupstate *pclk, 41typedef u32 clkgetfpoints(struct gk20a *g, struct clk_pmupstate *pclk,
38 struct clk_domain *pdomain, u32 *pfpointscount, 42 struct clk_domain *pdomain, u32 *pfpointscount,
39 u16 *pfreqpointsinmhz, u8 rail); 43 u16 *pfreqpointsinmhz, u8 rail);
@@ -100,6 +104,7 @@ struct clk_domain_3x_master {
100struct clk_domain_3x_slave { 104struct clk_domain_3x_slave {
101 struct clk_domain_3x_prog super; 105 struct clk_domain_3x_prog super;
102 u8 master_idx; 106 u8 master_idx;
107 clkgetslaveclk *clkdomainclkgetslaveclk;
103}; 108};
104 109
105u32 clk_domain_clk_prog_link(struct gk20a *g, struct clk_pmupstate *pclk); 110u32 clk_domain_clk_prog_link(struct gk20a *g, struct clk_pmupstate *pclk);
diff --git a/drivers/gpu/nvgpu/clk/clk_prog.c b/drivers/gpu/nvgpu/clk/clk_prog.c
index cb9a0e8d..9fdd8b25 100644
--- a/drivers/gpu/nvgpu/clk/clk_prog.c
+++ b/drivers/gpu/nvgpu/clk/clk_prog.c
@@ -31,6 +31,7 @@ static u32 devinit_get_clk_prog_table(struct gk20a *g,
31static vf_flatten vfflatten_prog_1x_master; 31static vf_flatten vfflatten_prog_1x_master;
32static vf_lookup vflookup_prog_1x_master; 32static vf_lookup vflookup_prog_1x_master;
33static get_fpoints getfpoints_prog_1x_master; 33static get_fpoints getfpoints_prog_1x_master;
34static get_slaveclk getslaveclk_prog_1x_master;
34 35
35static u32 _clk_progs_pmudatainit(struct gk20a *g, 36static u32 _clk_progs_pmudatainit(struct gk20a *g,
36 struct boardobjgrp *pboardobjgrp, 37 struct boardobjgrp *pboardobjgrp,
@@ -611,6 +612,9 @@ static u32 clk_prog_construct_1x_master(struct gk20a *g,
611 pclkprog->getfpoints = 612 pclkprog->getfpoints =
612 getfpoints_prog_1x_master; 613 getfpoints_prog_1x_master;
613 614
615 pclkprog->getslaveclk =
616 getslaveclk_prog_1x_master;
617
614 pclkprog->p_vf_entries = (struct ctrl_clk_clk_prog_1x_master_vf_entry *) 618 pclkprog->p_vf_entries = (struct ctrl_clk_clk_prog_1x_master_vf_entry *)
615 kzalloc(vfsize, GFP_KERNEL); 619 kzalloc(vfsize, GFP_KERNEL);
616 620
@@ -851,7 +855,7 @@ static u32 vflookup_prog_1x_master
851 u8 rail 855 u8 rail
852) 856)
853{ 857{
854 u8 j; 858 int j;
855 struct ctrl_clk_clk_prog_1x_master_vf_entry 859 struct ctrl_clk_clk_prog_1x_master_vf_entry
856 *pvfentry; 860 *pvfentry;
857 struct clk_vf_point *pvfpoint; 861 struct clk_vf_point *pvfpoint;
@@ -860,7 +864,7 @@ static u32 vflookup_prog_1x_master
860 u16 clkmhz; 864 u16 clkmhz;
861 u32 voltuv; 865 u32 voltuv;
862 u8 slaveentrycount; 866 u8 slaveentrycount;
863 u8 i; 867 int i;
864 struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry *pslaveents; 868 struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry *pslaveents;
865 869
866 if ((*pclkmhz != 0) && (*pvoltuv != 0)) 870 if ((*pclkmhz != 0) && (*pvoltuv != 0))
@@ -1045,3 +1049,50 @@ done:
1045 *pfpointscount = fpointscount; 1049 *pfpointscount = fpointscount;
1046 return 0; 1050 return 0;
1047} 1051}
1052
1053static int getslaveclk_prog_1x_master(struct gk20a *g,
1054 struct clk_pmupstate *pclk,
1055 struct clk_prog_1x_master *p1xmaster,
1056 u8 slave_clk_domain,
1057 u16 *pclkmhz,
1058 u16 masterclkmhz
1059)
1060{
1061 struct clk_progs *pclkprogobjs;
1062 struct clk_prog_1x_master_ratio *p1xmasterratio;
1063 u8 slaveentrycount;
1064 u8 i;
1065 struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry *pslaveents;
1066
1067 if (pclkmhz == NULL)
1068 return -EINVAL;
1069
1070 if (masterclkmhz == 0)
1071 return -EINVAL;
1072
1073 *pclkmhz = 0;
1074 pclkprogobjs = &(pclk->clk_progobjs);
1075
1076 slaveentrycount = pclkprogobjs->slave_entry_count;
1077
1078 if (p1xmaster->super.super.super.implements(g,
1079 &p1xmaster->super.super.super,
1080 CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO)) {
1081 p1xmasterratio =
1082 (struct clk_prog_1x_master_ratio *)p1xmaster;
1083 pslaveents = p1xmasterratio->p_slave_entries;
1084 for (i = 0; i < slaveentrycount; i++) {
1085 if (pslaveents->clk_dom_idx ==
1086 slave_clk_domain)
1087 break;
1088 pslaveents++;
1089 }
1090 if (i == slaveentrycount)
1091 return -EINVAL;
1092 *pclkmhz = (masterclkmhz * pslaveents->ratio)/100;
1093 } else {
1094 /* only support ratio for now */
1095 return -EINVAL;
1096 }
1097 return 0;
1098}
diff --git a/drivers/gpu/nvgpu/clk/clk_prog.h b/drivers/gpu/nvgpu/clk/clk_prog.h
index be92b3fc..60711b4c 100644
--- a/drivers/gpu/nvgpu/clk/clk_prog.h
+++ b/drivers/gpu/nvgpu/clk/clk_prog.h
@@ -32,6 +32,11 @@ typedef u32 vf_lookup(struct gk20a *g, struct clk_pmupstate *pclk,
32 u8 *slave_clk_domain_idx, u16 *pclkmhz, 32 u8 *slave_clk_domain_idx, u16 *pclkmhz,
33 u32 *pvoltuv, u8 rail); 33 u32 *pvoltuv, u8 rail);
34 34
35typedef int get_slaveclk(struct gk20a *g, struct clk_pmupstate *pclk,
36 struct clk_prog_1x_master *p1xmaster,
37 u8 slave_clk_domain_idx, u16 *pclkmhz,
38 u16 masterclkmhz);
39
35typedef u32 get_fpoints(struct gk20a *g, struct clk_pmupstate *pclk, 40typedef u32 get_fpoints(struct gk20a *g, struct clk_pmupstate *pclk,
36 struct clk_prog_1x_master *p1xmaster, 41 struct clk_prog_1x_master *p1xmaster,
37 u32 *pfpointscount, 42 u32 *pfpointscount,
@@ -65,6 +70,7 @@ struct clk_prog_1x_master {
65 vf_flatten *vfflatten; 70 vf_flatten *vfflatten;
66 vf_lookup *vflookup; 71 vf_lookup *vflookup;
67 get_fpoints *getfpoints; 72 get_fpoints *getfpoints;
73 get_slaveclk *getslaveclk;
68}; 74};
69 75
70struct clk_prog_1x_master_ratio { 76struct clk_prog_1x_master_ratio {
diff --git a/drivers/gpu/nvgpu/pstate/pstate.c b/drivers/gpu/nvgpu/pstate/pstate.c
index 94ff5010..d6173275 100644
--- a/drivers/gpu/nvgpu/pstate/pstate.c
+++ b/drivers/gpu/nvgpu/pstate/pstate.c
@@ -95,11 +95,11 @@ int gk20a_init_pstate_pmu_support(struct gk20a *g)
95 if (err) 95 if (err)
96 return err; 96 return err;
97 97
98 err = clk_pmu_vf_inject(g); 98 err = clk_vf_point_cache(g);
99 if (err) 99 if (err)
100 return err; 100 return err;
101 101
102 err = clk_vf_point_cache(g); 102 err = clk_set_boot_fll_clk(g);
103 return err; 103 return err;
104} 104}
105 105