summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPeter Boonstoppel <pboonstoppel@nvidia.com>2016-10-06 00:53:18 -0400
committerBharat Nihalani <bnihalani@nvidia.com>2016-10-17 05:09:28 -0400
commit2b593224dfbd93a34a31d5cd7654332f49d00d61 (patch)
tree260360fa47920eb590f5fcdfd5d361a206ba5078 /drivers
parentfa6ab1943e2977c64f62ba5b9c05b6d7fba234f3 (diff)
gpu: nvgpu: gm20b (un)railgate common clock support
Add support for GPU railgating using common clock framework and Tegra DVFS on k4.4 Bug: 200233943 Change-Id: Ief9afd7a5bf3f447e9b91ab181f26dcefff0a8c8 Signed-off-by: Peter Boonstoppel <pboonstoppel@nvidia.com> Reviewed-on: http://git-master/r/1232290 GVS: Gerrit_Virtual_Submit Reviewed-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c222
1 files changed, 137 insertions, 85 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c
index 90ba54ea..933fe2d8 100644
--- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c
+++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c
@@ -23,6 +23,7 @@
23#include <uapi/linux/nvgpu.h> 23#include <uapi/linux/nvgpu.h>
24#include <linux/dma-buf.h> 24#include <linux/dma-buf.h>
25#include <linux/nvmap.h> 25#include <linux/nvmap.h>
26#include <linux/reset.h>
26#include <linux/tegra_soctherm.h> 27#include <linux/tegra_soctherm.h>
27#include <linux/platform/tegra/clock.h> 28#include <linux/platform/tegra/clock.h>
28#include <linux/platform/tegra/dvfs.h> 29#include <linux/platform/tegra/dvfs.h>
@@ -47,6 +48,12 @@
47#define MC_CLIENT_GPU 34 48#define MC_CLIENT_GPU 34
48#define PMC_GPU_RG_CNTRL_0 0x2d4 49#define PMC_GPU_RG_CNTRL_0 0x2d4
49 50
51#ifdef CONFIG_COMMON_CLK
52#define GPU_RAIL_NAME "vdd-gpu"
53#else
54#define GPU_RAIL_NAME "vdd_gpu"
55#endif
56
50extern struct device tegra_vpr_dev; 57extern struct device tegra_vpr_dev;
51 58
52struct gk20a_emc_params { 59struct gk20a_emc_params {
@@ -304,23 +311,6 @@ static void gk20a_tegra_calibrate_emc(struct device *dev,
304 311
305#ifdef CONFIG_TEGRA_CLK_FRAMEWORK 312#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
306/* 313/*
307 * gk20a_tegra_is_railgated()
308 *
309 * Check status of gk20a power rail
310 */
311
312static bool gk20a_tegra_is_railgated(struct device *dev)
313{
314 struct gk20a_platform *platform = dev_get_drvdata(dev);
315 bool ret = false;
316
317 if (!(platform->is_fmodel))
318 ret = !tegra_dvfs_is_rail_up(platform->gpu_rail);
319
320 return ret;
321}
322
323/*
324 * gk20a_tegra_railgate() 314 * gk20a_tegra_railgate()
325 * 315 *
326 * Gate (disable) gk20a power rail 316 * Gate (disable) gk20a power rail
@@ -372,60 +362,6 @@ err_power_off:
372 return ret; 362 return ret;
373} 363}
374 364
375/*
376 * gm20b_tegra_railgate()
377 *
378 * Gate (disable) gm20b power rail
379 */
380
381static int gm20b_tegra_railgate(struct device *dev)
382{
383 struct gk20a_platform *platform = dev_get_drvdata(dev);
384 int ret = 0;
385
386 if (platform->is_fmodel ||
387 !tegra_dvfs_is_rail_up(platform->gpu_rail))
388 return 0;
389
390 tegra_mc_flush(MC_CLIENT_GPU);
391
392 udelay(10);
393
394 /* enable clamp */
395 pmc_write(0x1, PMC_GPU_RG_CNTRL_0);
396 pmc_read(PMC_GPU_RG_CNTRL_0);
397
398 udelay(10);
399
400 platform->reset_assert(dev);
401
402 udelay(10);
403
404 /*
405 * GPCPLL is already disabled before entering this function; reference
406 * clocks are enabled until now - disable them just before rail gating
407 */
408 clk_disable(platform->clk_reset);
409 clk_disable(platform->clk[0]);
410 clk_disable(platform->clk[1]);
411
412 udelay(10);
413
414 tegra_soctherm_gpu_tsens_invalidate(1);
415
416 if (tegra_dvfs_is_rail_up(platform->gpu_rail)) {
417 ret = tegra_dvfs_rail_power_down(platform->gpu_rail);
418 if (ret)
419 goto err_power_off;
420 } else
421 pr_info("No GPU regulator?\n");
422
423 return 0;
424
425err_power_off:
426 gk20a_err(dev, "Could not railgate GPU");
427 return ret;
428}
429 365
430/* 366/*
431 * gk20a_tegra_unrailgate() 367 * gk20a_tegra_unrailgate()
@@ -498,6 +434,84 @@ err_clk_on:
498 return ret; 434 return ret;
499} 435}
500 436
437#endif
438
439
440#if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_TEGRA_DVFS)
441/*
442 * gk20a_tegra_is_railgated()
443 *
444 * Check status of gk20a power rail
445 */
446
447static bool gk20a_tegra_is_railgated(struct device *dev)
448{
449 struct gk20a_platform *platform = dev_get_drvdata(dev);
450 bool ret = false;
451
452 if (!platform->is_fmodel)
453 ret = !tegra_dvfs_is_rail_up(platform->gpu_rail);
454
455 return ret;
456}
457
458
459/*
460 * gm20b_tegra_railgate()
461 *
462 * Gate (disable) gm20b power rail
463 */
464
465static int gm20b_tegra_railgate(struct device *dev)
466{
467 struct gk20a_platform *platform = dev_get_drvdata(dev);
468 int ret = 0;
469
470 if (platform->is_fmodel ||
471 !tegra_dvfs_is_rail_up(platform->gpu_rail))
472 return 0;
473
474 tegra_mc_flush(MC_CLIENT_GPU);
475
476 udelay(10);
477
478 /* enable clamp */
479 pmc_write(0x1, PMC_GPU_RG_CNTRL_0);
480 pmc_read(PMC_GPU_RG_CNTRL_0);
481
482 udelay(10);
483
484 platform->reset_assert(dev);
485
486 udelay(10);
487
488 /*
489 * GPCPLL is already disabled before entering this function; reference
490 * clocks are enabled until now - disable them just before rail gating
491 */
492 clk_disable_unprepare(platform->clk_reset);
493 clk_disable_unprepare(platform->clk[0]);
494 clk_disable_unprepare(platform->clk[1]);
495
496 udelay(10);
497
498 tegra_soctherm_gpu_tsens_invalidate(1);
499
500 if (tegra_dvfs_is_rail_up(platform->gpu_rail)) {
501 ret = tegra_dvfs_rail_power_down(platform->gpu_rail);
502 if (ret)
503 goto err_power_off;
504 } else
505 pr_info("No GPU regulator?\n");
506
507 return 0;
508
509err_power_off:
510 gk20a_err(dev, "Could not railgate GPU");
511 return ret;
512}
513
514
501/* 515/*
502 * gm20b_tegra_unrailgate() 516 * gm20b_tegra_unrailgate()
503 * 517 *
@@ -514,12 +528,14 @@ static int gm20b_tegra_unrailgate(struct device *dev)
514 return 0; 528 return 0;
515 529
516 if (!platform->gpu_rail) { 530 if (!platform->gpu_rail) {
517 platform->gpu_rail = tegra_dvfs_get_rail_by_name("vdd_gpu"); 531 platform->gpu_rail = tegra_dvfs_get_rail_by_name(GPU_RAIL_NAME);
518 if (IS_ERR_OR_NULL(platform->gpu_rail)) { 532 if (IS_ERR_OR_NULL(platform->gpu_rail)) {
519 WARN(1, "No GPU regulator?\n"); 533 WARN(1, "No GPU regulator?\n");
520 return -EINVAL; 534 return -EINVAL;
521 } 535 }
536#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
522 first = true; 537 first = true;
538#endif
523 } 539 }
524 540
525 ret = tegra_dvfs_rail_power_up(platform->gpu_rail); 541 ret = tegra_dvfs_rail_power_up(platform->gpu_rail);
@@ -528,19 +544,27 @@ static int gm20b_tegra_unrailgate(struct device *dev)
528 544
529 tegra_soctherm_gpu_tsens_invalidate(0); 545 tegra_soctherm_gpu_tsens_invalidate(0);
530 546
547 if (!platform->clk_reset) {
548 platform->clk_reset = clk_get(dev, "gpu_gate");
549 if (IS_ERR(platform->clk_reset)) {
550 gk20a_err(dev, "fail to get gpu reset clk\n");
551 goto err_clk_on;
552 }
553 }
554
531 if (!first) { 555 if (!first) {
532 ret = clk_enable(platform->clk_reset); 556 ret = clk_prepare_enable(platform->clk_reset);
533 if (ret) { 557 if (ret) {
534 gk20a_err(dev, "could not turn on gpu_gate"); 558 gk20a_err(dev, "could not turn on gpu_gate");
535 goto err_clk_on; 559 goto err_clk_on;
536 } 560 }
537 561
538 ret = clk_enable(platform->clk[0]); 562 ret = clk_prepare_enable(platform->clk[0]);
539 if (ret) { 563 if (ret) {
540 gk20a_err(dev, "could not turn on gpu pll"); 564 gk20a_err(dev, "could not turn on gpu pll");
541 goto err_clk_on; 565 goto err_clk_on;
542 } 566 }
543 ret = clk_enable(platform->clk[1]); 567 ret = clk_prepare_enable(platform->clk[1]);
544 if (ret) { 568 if (ret) {
545 gk20a_err(dev, "could not turn on pwr clock"); 569 gk20a_err(dev, "could not turn on pwr clock");
546 goto err_clk_on; 570 goto err_clk_on;
@@ -580,13 +604,23 @@ err_clk_on:
580} 604}
581#endif 605#endif
582 606
607
583static struct { 608static struct {
584 char *name; 609 char *name;
585 unsigned long default_rate; 610 unsigned long default_rate;
586} tegra_gk20a_clocks[] = { 611} tegra_gk20a_clocks[] = {
612#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
587 {"PLLG_ref", UINT_MAX}, 613 {"PLLG_ref", UINT_MAX},
588 {"pwr", 204000000}, 614 {"pwr", 204000000},
589 {"emc", UINT_MAX} }; 615 {"emc", UINT_MAX},
616#elif defined(CONFIG_COMMON_CLK)
617 {"gpu_ref", UINT_MAX},
618 {"pll_p_out5", 204000000},
619 {"emc", UINT_MAX},
620#endif
621};
622
623
590 624
591/* 625/*
592 * gk20a_tegra_get_clocks() 626 * gk20a_tegra_get_clocks()
@@ -653,22 +687,31 @@ static int gk20a_tegra_reset_deassert(struct device *dev)
653 return 0; 687 return 0;
654} 688}
655 689
690#if defined(CONFIG_RESET_CONTROLLER) && defined(CONFIG_COMMON_CLK)
656static int gm20b_tegra_reset_assert(struct device *dev) 691static int gm20b_tegra_reset_assert(struct device *dev)
657{ 692{
658 struct gk20a_platform *platform = gk20a_get_platform(dev); 693 struct gk20a_platform *platform = gk20a_get_platform(dev);
659 694
660 if (!platform->clk_reset) { 695 if (!platform->reset_control) {
661 platform->clk_reset = clk_get(dev, "gpu_gate"); 696 WARN(1, "Reset control not initialized\n");
662 if (IS_ERR(platform->clk_reset)) { 697 return -ENOSYS;
663 gk20a_err(dev, "fail to get gpu reset clk\n");
664 return PTR_ERR(platform->clk_reset);
665 }
666 } 698 }
667 699
668 tegra_periph_reset_assert(platform->clk_reset); 700 return reset_control_assert(platform->reset_control);
701}
669 702
670 return 0; 703static int gm20b_tegra_reset_deassert(struct device *dev)
704{
705 struct gk20a_platform *platform = gk20a_get_platform(dev);
706
707 if (!platform->reset_control) {
708 WARN(1, "Reset control not initialized\n");
709 return -ENOSYS;
710 }
711
712 return reset_control_deassert(platform->reset_control);
671} 713}
714#endif
672 715
673static void gk20a_tegra_scale_init(struct device *dev) 716static void gk20a_tegra_scale_init(struct device *dev)
674{ 717{
@@ -778,6 +821,10 @@ static int gk20a_tegra_probe(struct device *dev)
778 821
779 gk20a_tegra_get_clocks(dev); 822 gk20a_tegra_get_clocks(dev);
780 823
824#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
825 pmc = ioremap(TEGRA_PMC_BASE, 4096);
826#endif
827
781 return 0; 828 return 0;
782} 829}
783 830
@@ -935,7 +982,7 @@ struct gk20a_platform gm20b_tegra_platform = {
935 982
936 /* power management callbacks */ 983 /* power management callbacks */
937 .suspend = gk20a_tegra_suspend, 984 .suspend = gk20a_tegra_suspend,
938#ifdef CONFIG_TEGRA_CLK_FRAMEWORK 985#if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_TEGRA_DVFS)
939 .railgate = gm20b_tegra_railgate, 986 .railgate = gm20b_tegra_railgate,
940 .unrailgate = gm20b_tegra_unrailgate, 987 .unrailgate = gm20b_tegra_unrailgate,
941 .is_railgated = gk20a_tegra_is_railgated, 988 .is_railgated = gk20a_tegra_is_railgated,
@@ -944,8 +991,13 @@ struct gk20a_platform gm20b_tegra_platform = {
944 .busy = gk20a_tegra_busy, 991 .busy = gk20a_tegra_busy,
945 .idle = gk20a_tegra_idle, 992 .idle = gk20a_tegra_idle,
946 993
994#if defined(CONFIG_RESET_CONTROLLER) && defined(CONFIG_COMMON_CLK)
947 .reset_assert = gm20b_tegra_reset_assert, 995 .reset_assert = gm20b_tegra_reset_assert,
996 .reset_deassert = gm20b_tegra_reset_deassert,
997#else
998 .reset_assert = gk20a_tegra_reset_assert,
948 .reset_deassert = gk20a_tegra_reset_deassert, 999 .reset_deassert = gk20a_tegra_reset_deassert,
1000#endif
949 1001
950#ifdef CONFIG_TEGRA_CLK_FRAMEWORK 1002#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
951 .clk_get_rate = gk20a_get_clk_rate, 1003 .clk_get_rate = gk20a_get_clk_rate,