diff options
author | David Nieto <dmartineznie@nvidia.com> | 2016-11-04 01:01:32 -0400 |
---|---|---|
committer | Deepak Nibade <dnibade@nvidia.com> | 2016-12-27 04:56:52 -0500 |
commit | 2f258670e40be1c92ab57b6fe77908add768ad9d (patch) | |
tree | 77e4fe65923a4e6667ac6956d1e2de158655c5e8 /drivers/gpu/nvgpu/clk/clk.c | |
parent | 2ebf09920755daeb7e1be71bf317f88ec9d533e1 (diff) |
gpu: nvgpu: p-state bound arbiter
Modification of the ARBITER clocks to be P-State aware
Up to now the arbiter just considered the whole range
of the GPC and MCLK domains, which could end up on
illegal combinations of MCLK, GPC2CLK, and set the
SYSCLK and XBARCLK domains below their minimum VCO
The following has been implemented:
(1) Modified VF tables to add which PState are
supported on each point.
(2) Return and store the current PState on the
arbiter state.
(3) Modified logic to prevent illegal combinations of
MCLK and GPC2CLK.
(4) Modified logic to prevent setting VF points for
XBAR and SYS domains below VCO limits.
(5) Modified voltage calculation to account for increased
values of XBAR and SYS on some VF points.
(6) Modified arbiter clock target logic to prevent an
application that has not requested a particular VF point
to set target to default targets.
(7) Remove unnecesary mutexes from critical path
JIRA DNVGPU-182
JIRA DNVGPU-183
Change-Id: I3d1c30903278f848681b8da833a867835acc99bb
Signed-off-by: David Nieto <dmartineznie@nvidia.com>
Reviewed-on: http://git-master/r/1247937
(cherry picked from commit b8bcc07eb3b5b70ec1ee19ace237df99d6170138)
Reviewed-on: http://git-master/r/1268063
Tested-by: Thomas Fleury <tfleury@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/clk/clk.c')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk.c | 136 |
1 files changed, 63 insertions, 73 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c index bec5fad1..07c80e22 100644 --- a/drivers/gpu/nvgpu/clk/clk.c +++ b/drivers/gpu/nvgpu/clk/clk.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "volt/volt.h" | 20 | #include "volt/volt.h" |
21 | #include "gk20a/pmu_gk20a.h" | 21 | #include "gk20a/pmu_gk20a.h" |
22 | 22 | ||
23 | #define BOOT_GPC2CLK_MHZ 2581 | ||
23 | #define BOOT_MCLK_MHZ 3003 | 24 | #define BOOT_MCLK_MHZ 3003 |
24 | 25 | ||
25 | struct clkrpc_pmucmdhandler_params { | 26 | struct clkrpc_pmucmdhandler_params { |
@@ -255,7 +256,61 @@ static int get_regime_id(struct gk20a *g, u32 domain, u32 *regimeid) | |||
255 | return -EINVAL; | 256 | return -EINVAL; |
256 | } | 257 | } |
257 | 258 | ||
258 | int clk_program_fll_clks(struct gk20a *g, struct change_fll_clk *fllclk) | 259 | int clk_set_fll_clks(struct gk20a *g, struct set_fll_clk *setfllclk) |
260 | { | ||
261 | int status = -EINVAL; | ||
262 | |||
263 | /*set regime ids */ | ||
264 | status = get_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
265 | &setfllclk->current_regime_id_gpc); | ||
266 | if (status) | ||
267 | goto done; | ||
268 | |||
269 | setfllclk->target_regime_id_gpc = find_regime_id(g, | ||
270 | CTRL_CLK_DOMAIN_GPC2CLK, setfllclk->gpc2clkmhz); | ||
271 | |||
272 | status = get_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK, | ||
273 | &setfllclk->current_regime_id_sys); | ||
274 | if (status) | ||
275 | goto done; | ||
276 | |||
277 | setfllclk->target_regime_id_sys = find_regime_id(g, | ||
278 | CTRL_CLK_DOMAIN_SYS2CLK, setfllclk->sys2clkmhz); | ||
279 | |||
280 | status = get_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK, | ||
281 | &setfllclk->current_regime_id_xbar); | ||
282 | if (status) | ||
283 | goto done; | ||
284 | |||
285 | setfllclk->target_regime_id_xbar = find_regime_id(g, | ||
286 | CTRL_CLK_DOMAIN_XBAR2CLK, setfllclk->xbar2clkmhz); | ||
287 | |||
288 | status = clk_pmu_vf_inject(g, setfllclk); | ||
289 | |||
290 | if (status) | ||
291 | gk20a_err(dev_from_gk20a(g), | ||
292 | "vf inject to change clk failed"); | ||
293 | |||
294 | /* save regime ids */ | ||
295 | status = set_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK, | ||
296 | setfllclk->target_regime_id_xbar); | ||
297 | if (status) | ||
298 | goto done; | ||
299 | |||
300 | status = set_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
301 | setfllclk->target_regime_id_gpc); | ||
302 | if (status) | ||
303 | goto done; | ||
304 | |||
305 | status = set_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK, | ||
306 | setfllclk->target_regime_id_sys); | ||
307 | if (status) | ||
308 | goto done; | ||
309 | done: | ||
310 | return status; | ||
311 | } | ||
312 | |||
313 | int clk_get_fll_clks(struct gk20a *g, struct set_fll_clk *setfllclk) | ||
259 | { | 314 | { |
260 | int status = -EINVAL; | 315 | int status = -EINVAL; |
261 | struct clk_domain *pdomain; | 316 | struct clk_domain *pdomain; |
@@ -265,25 +320,14 @@ int clk_program_fll_clks(struct gk20a *g, struct change_fll_clk *fllclk) | |||
265 | struct clk_domain_3x_master *p3xmaster; | 320 | struct clk_domain_3x_master *p3xmaster; |
266 | struct clk_domain_3x_slave *p3xslave; | 321 | struct clk_domain_3x_slave *p3xslave; |
267 | unsigned long slaveidxmask; | 322 | unsigned long slaveidxmask; |
268 | struct set_fll_clk setfllclk; | ||
269 | bool foundxbar2clk = false; | ||
270 | bool foundsys2clk = false; | ||
271 | 323 | ||
272 | memset(&setfllclk, 0, sizeof(setfllclk)); | 324 | if (setfllclk->gpc2clkmhz == 0) |
273 | if (fllclk->api_clk_domain != CTRL_CLK_DOMAIN_GPC2CLK) | ||
274 | return -EINVAL; | ||
275 | if (fllclk->voltuv == 0) | ||
276 | return -EINVAL; | 325 | return -EINVAL; |
277 | if (fllclk->clkmhz == 0) | ||
278 | return -EINVAL; | ||
279 | |||
280 | setfllclk.voltuv = fllclk->voltuv; | ||
281 | setfllclk.gpc2clkmhz = fllclk->clkmhz; | ||
282 | 326 | ||
283 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | 327 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), |
284 | struct clk_domain *, pdomain, i) { | 328 | struct clk_domain *, pdomain, i) { |
285 | 329 | ||
286 | if (pdomain->api_domain == fllclk->api_clk_domain) { | 330 | if (pdomain->api_domain == CTRL_CLK_DOMAIN_GPC2CLK) { |
287 | 331 | ||
288 | if (!pdomain->super.implements(g, &pdomain->super, | 332 | if (!pdomain->super.implements(g, &pdomain->super, |
289 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) { | 333 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) { |
@@ -305,74 +349,20 @@ int clk_program_fll_clks(struct gk20a *g, struct change_fll_clk *fllclk) | |||
305 | pclk, | 349 | pclk, |
306 | (struct clk_domain *)p3xslave, | 350 | (struct clk_domain *)p3xslave, |
307 | &clkmhz, | 351 | &clkmhz, |
308 | fllclk->clkmhz); | 352 | setfllclk->gpc2clkmhz); |
309 | if (status) { | 353 | if (status) { |
310 | status = -EINVAL; | 354 | status = -EINVAL; |
311 | goto done; | 355 | goto done; |
312 | } | 356 | } |
313 | if (p3xslave->super.super.super.api_domain == | 357 | if (p3xslave->super.super.super.api_domain == |
314 | CTRL_CLK_DOMAIN_XBAR2CLK) { | 358 | CTRL_CLK_DOMAIN_XBAR2CLK) |
315 | setfllclk.xbar2clkmhz = clkmhz; | 359 | setfllclk->xbar2clkmhz = clkmhz; |
316 | foundxbar2clk = true; | ||
317 | } | ||
318 | if (p3xslave->super.super.super.api_domain == | 360 | if (p3xslave->super.super.super.api_domain == |
319 | CTRL_CLK_DOMAIN_SYS2CLK) { | 361 | CTRL_CLK_DOMAIN_SYS2CLK) |
320 | setfllclk.sys2clkmhz = clkmhz; | 362 | setfllclk->sys2clkmhz = clkmhz; |
321 | foundsys2clk = true; | ||
322 | } | ||
323 | } | 363 | } |
324 | } | 364 | } |
325 | } | 365 | } |
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; | ||
376 | done: | 366 | done: |
377 | return status; | 367 | return status; |
378 | } | 368 | } |