diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/clk_gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/clk_gm20b.c | 51 |
2 files changed, 29 insertions, 23 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/clk_gk20a.h b/drivers/gpu/nvgpu/gk20a/clk_gk20a.h index e6d14f74..274194be 100644 --- a/drivers/gpu/nvgpu/gk20a/clk_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/clk_gk20a.h | |||
@@ -52,6 +52,7 @@ struct clk_gk20a { | |||
52 | struct gk20a *g; | 52 | struct gk20a *g; |
53 | struct clk *tegra_clk; | 53 | struct clk *tegra_clk; |
54 | struct pll gpc_pll; | 54 | struct pll gpc_pll; |
55 | struct pll gpc_pll_last; | ||
55 | u32 pll_delay; /* default PLL settle time */ | 56 | u32 pll_delay; /* default PLL settle time */ |
56 | struct mutex clk_mutex; | 57 | struct mutex clk_mutex; |
57 | bool sw_ready; | 58 | bool sw_ready; |
diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c index 4c1b9012..c7c2e8af 100644 --- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c | |||
@@ -453,7 +453,6 @@ static int clk_program_gpc_pll(struct gk20a *g, struct pll *gpll_new, | |||
453 | gpll.PL = (gpll_new->PL < 2) ? 2 : gpll_new->PL; | 453 | gpll.PL = (gpll_new->PL < 2) ? 2 : gpll_new->PL; |
454 | #endif | 454 | #endif |
455 | clk_lock_gpc_pll_under_bypass(g, &gpll); | 455 | clk_lock_gpc_pll_under_bypass(g, &gpll); |
456 | gpll_new->enabled = true; | ||
457 | 456 | ||
458 | #if PLDIV_GLITCHLESS | 457 | #if PLDIV_GLITCHLESS |
459 | coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r()); | 458 | coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r()); |
@@ -646,28 +645,31 @@ static int set_pll_target(struct gk20a *g, u32 freq, u32 old_freq) | |||
646 | return 0; | 645 | return 0; |
647 | } | 646 | } |
648 | 647 | ||
649 | static int set_pll_freq(struct gk20a *g, u32 freq, u32 old_freq) | 648 | static int set_pll_freq(struct gk20a *g, int allow_slide) |
650 | { | 649 | { |
651 | struct clk_gk20a *clk = &g->clk; | 650 | struct clk_gk20a *clk = &g->clk; |
652 | int err = 0; | 651 | int err = 0; |
653 | 652 | ||
654 | gk20a_dbg_fn("curr freq: %dMHz, target freq %dMHz", old_freq, freq); | 653 | gk20a_dbg_fn("last freq: %dMHz, target freq %dMHz", |
654 | clk->gpc_pll_last.freq, clk->gpc_pll.freq); | ||
655 | 655 | ||
656 | if ((freq == old_freq) && clk->gpc_pll.enabled) | 656 | /* If programming with dynamic sliding failed, re-try under bypass */ |
657 | return 0; | 657 | err = clk_program_gpc_pll(g, &clk->gpc_pll, allow_slide); |
658 | if (err && allow_slide) | ||
659 | err = clk_program_gpc_pll(g, &clk->gpc_pll, 0); | ||
658 | 660 | ||
659 | /* change frequency only if power is on */ | 661 | if (!err) { |
660 | if (g->clk.clk_hw_on) { | 662 | clk->gpc_pll.enabled = true; |
661 | err = clk_program_gpc_pll(g, &clk->gpc_pll, 1); | 663 | clk->gpc_pll_last = clk->gpc_pll; |
662 | if (err) | 664 | return 0; |
663 | err = clk_program_gpc_pll(g, &clk->gpc_pll, 0); | ||
664 | } | 665 | } |
665 | 666 | ||
666 | /* Just report error but not restore PLL since dvfs could already change | 667 | /* |
667 | voltage even when it returns error. */ | 668 | * Just report error but not restore PLL since dvfs could already change |
668 | if (err) | 669 | * voltage even when programming failed. |
669 | gk20a_err(dev_from_gk20a(g), | 670 | */ |
670 | "failed to set pll to %d", freq); | 671 | gk20a_err(dev_from_gk20a(g), "failed to set pll to %d", |
672 | clk->gpc_pll.freq); | ||
671 | return err; | 673 | return err; |
672 | } | 674 | } |
673 | 675 | ||
@@ -682,8 +684,8 @@ static int gm20b_clk_export_set_rate(void *data, unsigned long *rate) | |||
682 | mutex_lock(&clk->clk_mutex); | 684 | mutex_lock(&clk->clk_mutex); |
683 | old_freq = clk->gpc_pll.freq; | 685 | old_freq = clk->gpc_pll.freq; |
684 | ret = set_pll_target(g, rate_gpu_to_gpc2clk(*rate), old_freq); | 686 | ret = set_pll_target(g, rate_gpu_to_gpc2clk(*rate), old_freq); |
685 | if (!ret && clk->gpc_pll.enabled) | 687 | if (!ret && clk->gpc_pll.enabled && clk->clk_hw_on) |
686 | ret = set_pll_freq(g, clk->gpc_pll.freq, old_freq); | 688 | ret = set_pll_freq(g, 1); |
687 | if (!ret) | 689 | if (!ret) |
688 | *rate = rate_gpc2clk_to_gpu(clk->gpc_pll.freq); | 690 | *rate = rate_gpc2clk_to_gpu(clk->gpc_pll.freq); |
689 | mutex_unlock(&clk->clk_mutex); | 691 | mutex_unlock(&clk->clk_mutex); |
@@ -693,12 +695,13 @@ static int gm20b_clk_export_set_rate(void *data, unsigned long *rate) | |||
693 | 695 | ||
694 | static int gm20b_clk_export_enable(void *data) | 696 | static int gm20b_clk_export_enable(void *data) |
695 | { | 697 | { |
696 | int ret; | 698 | int ret = 0; |
697 | struct gk20a *g = data; | 699 | struct gk20a *g = data; |
698 | struct clk_gk20a *clk = &g->clk; | 700 | struct clk_gk20a *clk = &g->clk; |
699 | 701 | ||
700 | mutex_lock(&clk->clk_mutex); | 702 | mutex_lock(&clk->clk_mutex); |
701 | ret = set_pll_freq(g, clk->gpc_pll.freq, clk->gpc_pll.freq); | 703 | if (!clk->gpc_pll.enabled && clk->clk_hw_on) |
704 | ret = set_pll_freq(g, 1); | ||
702 | mutex_unlock(&clk->clk_mutex); | 705 | mutex_unlock(&clk->clk_mutex); |
703 | return ret; | 706 | return ret; |
704 | } | 707 | } |
@@ -709,7 +712,7 @@ static void gm20b_clk_export_disable(void *data) | |||
709 | struct clk_gk20a *clk = &g->clk; | 712 | struct clk_gk20a *clk = &g->clk; |
710 | 713 | ||
711 | mutex_lock(&clk->clk_mutex); | 714 | mutex_lock(&clk->clk_mutex); |
712 | if (g->clk.clk_hw_on) | 715 | if (clk->gpc_pll.enabled && clk->clk_hw_on) |
713 | clk_disable_gpcpll(g, 1); | 716 | clk_disable_gpcpll(g, 1); |
714 | mutex_unlock(&clk->clk_mutex); | 717 | mutex_unlock(&clk->clk_mutex); |
715 | } | 718 | } |
@@ -789,7 +792,8 @@ static int gm20b_init_clk_support(struct gk20a *g) | |||
789 | 792 | ||
790 | /* The prev call may not enable PLL if gbus is unbalanced - force it */ | 793 | /* The prev call may not enable PLL if gbus is unbalanced - force it */ |
791 | mutex_lock(&clk->clk_mutex); | 794 | mutex_lock(&clk->clk_mutex); |
792 | err = set_pll_freq(g, clk->gpc_pll.freq, clk->gpc_pll.freq); | 795 | if (!clk->gpc_pll.enabled) |
796 | err = set_pll_freq(g, 1); | ||
793 | mutex_unlock(&clk->clk_mutex); | 797 | mutex_unlock(&clk->clk_mutex); |
794 | if (err) | 798 | if (err) |
795 | return err; | 799 | return err; |
@@ -805,13 +809,14 @@ static int gm20b_init_clk_support(struct gk20a *g) | |||
805 | 809 | ||
806 | static int gm20b_suspend_clk_support(struct gk20a *g) | 810 | static int gm20b_suspend_clk_support(struct gk20a *g) |
807 | { | 811 | { |
808 | int ret; | 812 | int ret = 0; |
809 | 813 | ||
810 | clk_disable(g->clk.tegra_clk); | 814 | clk_disable(g->clk.tegra_clk); |
811 | 815 | ||
812 | /* The prev call may not disable PLL if gbus is unbalanced - force it */ | 816 | /* The prev call may not disable PLL if gbus is unbalanced - force it */ |
813 | mutex_lock(&g->clk.clk_mutex); | 817 | mutex_lock(&g->clk.clk_mutex); |
814 | ret = clk_disable_gpcpll(g, 1); | 818 | if (g->clk.gpc_pll.enabled) |
819 | ret = clk_disable_gpcpll(g, 1); | ||
815 | g->clk.clk_hw_on = false; | 820 | g->clk.clk_hw_on = false; |
816 | mutex_unlock(&g->clk.clk_mutex); | 821 | mutex_unlock(&g->clk.clk_mutex); |
817 | return ret; | 822 | return ret; |