diff options
author | Srikar Srimath Tirumala <srikars@nvidia.com> | 2017-01-11 18:35:21 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-02-07 19:04:39 -0500 |
commit | 3335ff9fe90d3f523a463107bae864b011590182 (patch) | |
tree | 2d7d85333c4d9c19b8fa40a2881e3610ce10827d /drivers/gpu/nvgpu | |
parent | 521253acb761041a5d9ba97a7a789fe02682a03d (diff) |
gpu: nvgpu: add support for EMC freq scaling
Add support to do EMC frequency scaling via bwmgr on T210 K4.4.
Bug 200267304
Change-Id: Ib01f1a256cfceefc5551e128b7ba8953fafe21d3
Signed-off-by: Srikar Srimath Tirumala <srikars@nvidia.com>
Reviewed-on: http://git-master/r/1285001
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Peter Boonstoppel <pboonstoppel@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jon Mayo <jmayo@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | 91 |
1 files changed, 87 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c index c18f0230..a373f487 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | |||
@@ -38,6 +38,9 @@ | |||
38 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) | 38 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) |
39 | #include <soc/tegra/fuse.h> | 39 | #include <soc/tegra/fuse.h> |
40 | #endif | 40 | #endif |
41 | #ifdef CONFIG_TEGRA_BWMGR | ||
42 | #include <linux/platform/tegra/emc_bwmgr.h> | ||
43 | #endif | ||
41 | 44 | ||
42 | #include <linux/platform/tegra/tegra_emc.h> | 45 | #include <linux/platform/tegra/tegra_emc.h> |
43 | 46 | ||
@@ -62,10 +65,18 @@ | |||
62 | 65 | ||
63 | extern struct device tegra_vpr_dev; | 66 | extern struct device tegra_vpr_dev; |
64 | 67 | ||
68 | #ifdef CONFIG_TEGRA_BWMGR | ||
65 | struct gk20a_emc_params { | 69 | struct gk20a_emc_params { |
66 | unsigned long bw_ratio; | 70 | unsigned long bw_ratio; |
67 | unsigned long freq_last_set; | 71 | unsigned long freq_last_set; |
72 | struct tegra_bwmgr_client *bwmgr_cl; | ||
68 | }; | 73 | }; |
74 | #else | ||
75 | struct gk20a_emc_params { | ||
76 | unsigned long bw_ratio; | ||
77 | unsigned long freq_last_set; | ||
78 | }; | ||
79 | #endif | ||
69 | 80 | ||
70 | static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); | 81 | static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); |
71 | static inline u32 __maybe_unused pmc_read(unsigned long reg) | 82 | static inline u32 __maybe_unused pmc_read(unsigned long reg) |
@@ -317,6 +328,51 @@ static void gk20a_tegra_calibrate_emc(struct device *dev, | |||
317 | emc_params->bw_ratio = (gpu_bw / emc_bw); | 328 | emc_params->bw_ratio = (gpu_bw / emc_bw); |
318 | } | 329 | } |
319 | 330 | ||
331 | #ifdef CONFIG_TEGRA_BWMGR | ||
332 | void gm20b_bwmgr_set_rate(struct gk20a_platform *platform, bool enb) | ||
333 | { | ||
334 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
335 | struct gk20a_emc_params *params; | ||
336 | unsigned long rate; | ||
337 | |||
338 | if (!profile || !profile->private_data) | ||
339 | return; | ||
340 | |||
341 | params = (struct gk20a_emc_params *)profile->private_data; | ||
342 | rate = (enb) ? params->freq_last_set : 0; | ||
343 | tegra_bwmgr_set_emc(params->bwmgr_cl, rate, TEGRA_BWMGR_SET_EMC_FLOOR); | ||
344 | } | ||
345 | |||
346 | static void gm20b_tegra_postscale(struct device *dev, unsigned long freq) | ||
347 | { | ||
348 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
349 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
350 | struct gk20a_emc_params *emc_params; | ||
351 | unsigned long emc_rate; | ||
352 | |||
353 | if (!profile) | ||
354 | return; | ||
355 | |||
356 | emc_params = profile->private_data; | ||
357 | emc_rate = gk20a_tegra_get_emc_rate(get_gk20a(dev), emc_params); | ||
358 | |||
359 | if (emc_rate > tegra_bwmgr_get_max_emc_rate()) | ||
360 | emc_rate = tegra_bwmgr_get_max_emc_rate(); | ||
361 | |||
362 | emc_params->freq_last_set = emc_rate; | ||
363 | mutex_lock(&platform->railgate_lock); | ||
364 | if (platform->is_railgated && !platform->is_railgated(dev)) | ||
365 | goto done; | ||
366 | |||
367 | tegra_bwmgr_set_emc(emc_params->bwmgr_cl, emc_rate, | ||
368 | TEGRA_BWMGR_SET_EMC_FLOOR); | ||
369 | |||
370 | done: | ||
371 | mutex_unlock(&platform->railgate_lock); | ||
372 | } | ||
373 | |||
374 | #endif | ||
375 | |||
320 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK | 376 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK |
321 | /* | 377 | /* |
322 | * gk20a_tegra_railgate() | 378 | * gk20a_tegra_railgate() |
@@ -463,7 +519,6 @@ static bool gk20a_tegra_is_railgated(struct device *dev) | |||
463 | return ret; | 519 | return ret; |
464 | } | 520 | } |
465 | 521 | ||
466 | |||
467 | /* | 522 | /* |
468 | * gm20b_tegra_railgate() | 523 | * gm20b_tegra_railgate() |
469 | * | 524 | * |
@@ -514,6 +569,10 @@ static int gm20b_tegra_railgate(struct device *dev) | |||
514 | } else | 569 | } else |
515 | pr_info("No GPU regulator?\n"); | 570 | pr_info("No GPU regulator?\n"); |
516 | 571 | ||
572 | #ifdef CONFIG_TEGRA_BWMGR | ||
573 | gm20b_bwmgr_set_rate(platform, false); | ||
574 | #endif | ||
575 | |||
517 | return 0; | 576 | return 0; |
518 | 577 | ||
519 | err_power_off: | 578 | err_power_off: |
@@ -552,6 +611,10 @@ static int gm20b_tegra_unrailgate(struct device *dev) | |||
552 | if (ret) | 611 | if (ret) |
553 | return ret; | 612 | return ret; |
554 | 613 | ||
614 | #ifdef CONFIG_TEGRA_BWMGR | ||
615 | gm20b_bwmgr_set_rate(platform, true); | ||
616 | #endif | ||
617 | |||
555 | tegra_soctherm_gpu_tsens_invalidate(0); | 618 | tegra_soctherm_gpu_tsens_invalidate(0); |
556 | 619 | ||
557 | if (!platform->clk_reset) { | 620 | if (!platform->clk_reset) { |
@@ -750,6 +813,14 @@ static void gk20a_tegra_scale_init(struct device *dev) | |||
750 | emc_params->freq_last_set = -1; | 813 | emc_params->freq_last_set = -1; |
751 | gk20a_tegra_calibrate_emc(dev, emc_params); | 814 | gk20a_tegra_calibrate_emc(dev, emc_params); |
752 | 815 | ||
816 | #ifdef CONFIG_TEGRA_BWMGR | ||
817 | emc_params->bwmgr_cl = tegra_bwmgr_register(TEGRA_BWMGR_CLIENT_GPU); | ||
818 | if (!emc_params->bwmgr_cl) { | ||
819 | gk20a_dbg_info("%s Missing GPU BWMGR client\n", __func__); | ||
820 | return; | ||
821 | } | ||
822 | #endif | ||
823 | |||
753 | profile->private_data = emc_params; | 824 | profile->private_data = emc_params; |
754 | } | 825 | } |
755 | 826 | ||
@@ -757,9 +828,17 @@ static void gk20a_tegra_scale_exit(struct device *dev) | |||
757 | { | 828 | { |
758 | struct gk20a_platform *platform = dev_get_drvdata(dev); | 829 | struct gk20a_platform *platform = dev_get_drvdata(dev); |
759 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | 830 | struct gk20a_scale_profile *profile = platform->g->scale_profile; |
831 | struct gk20a_emc_params *emc_params; | ||
832 | |||
833 | if (!profile) | ||
834 | return; | ||
760 | 835 | ||
761 | if (profile) | 836 | emc_params = profile->private_data; |
762 | kfree(profile->private_data); | 837 | #ifdef CONFIG_TEGRA_BWMGR |
838 | tegra_bwmgr_unregister(emc_params->bwmgr_cl); | ||
839 | #endif | ||
840 | |||
841 | kfree(profile->private_data); | ||
763 | } | 842 | } |
764 | 843 | ||
765 | void gk20a_tegra_debug_dump(struct device *dev) | 844 | void gk20a_tegra_debug_dump(struct device *dev) |
@@ -1027,9 +1106,9 @@ struct gk20a_platform gm20b_tegra_platform = { | |||
1027 | .probe = gk20a_tegra_probe, | 1106 | .probe = gk20a_tegra_probe, |
1028 | .late_probe = gk20a_tegra_late_probe, | 1107 | .late_probe = gk20a_tegra_late_probe, |
1029 | .remove = gk20a_tegra_remove, | 1108 | .remove = gk20a_tegra_remove, |
1030 | |||
1031 | /* power management callbacks */ | 1109 | /* power management callbacks */ |
1032 | .suspend = gk20a_tegra_suspend, | 1110 | .suspend = gk20a_tegra_suspend, |
1111 | |||
1033 | #if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_TEGRA_DVFS) | 1112 | #if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_TEGRA_DVFS) |
1034 | .railgate = gm20b_tegra_railgate, | 1113 | .railgate = gm20b_tegra_railgate, |
1035 | .unrailgate = gm20b_tegra_unrailgate, | 1114 | .unrailgate = gm20b_tegra_unrailgate, |
@@ -1060,7 +1139,11 @@ struct gk20a_platform gm20b_tegra_platform = { | |||
1060 | 1139 | ||
1061 | /* frequency scaling configuration */ | 1140 | /* frequency scaling configuration */ |
1062 | .prescale = gk20a_tegra_prescale, | 1141 | .prescale = gk20a_tegra_prescale, |
1142 | #ifdef CONFIG_TEGRA_BWMGR | ||
1143 | .postscale = gm20b_tegra_postscale, | ||
1144 | #else | ||
1063 | .postscale = gk20a_tegra_postscale, | 1145 | .postscale = gk20a_tegra_postscale, |
1146 | #endif | ||
1064 | .devfreq_governor = "nvhost_podgov", | 1147 | .devfreq_governor = "nvhost_podgov", |
1065 | .qos_notify = gk20a_scale_qos_notify, | 1148 | .qos_notify = gk20a_scale_qos_notify, |
1066 | 1149 | ||