aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c40
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.h2
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c27
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h3
4 files changed, 67 insertions, 5 deletions
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 613d639833c0..d4e98e5876bc 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -61,8 +61,10 @@ static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
61 A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF)); 61 A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
62} 62}
63 63
64static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) 64static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
65{ 65{
66 int ret;
67
66 gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0); 68 gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0);
67 69
68 gmu_write(gmu, REG_A6XX_GMU_DCVS_PERF_SETTING, 70 gmu_write(gmu, REG_A6XX_GMU_DCVS_PERF_SETTING,
@@ -78,7 +80,37 @@ static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
78 a6xx_gmu_set_oob(gmu, GMU_OOB_DCVS_SET); 80 a6xx_gmu_set_oob(gmu, GMU_OOB_DCVS_SET);
79 a6xx_gmu_clear_oob(gmu, GMU_OOB_DCVS_SET); 81 a6xx_gmu_clear_oob(gmu, GMU_OOB_DCVS_SET);
80 82
81 return gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN); 83 ret = gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN);
84 if (ret)
85 dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
86
87 gmu->freq = gmu->gpu_freqs[index];
88}
89
90void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
91{
92 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
93 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
94 struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
95 u32 perf_index = 0;
96
97 if (freq == gmu->freq)
98 return;
99
100 for (perf_index = 0; perf_index < gmu->nr_gpu_freqs - 1; perf_index++)
101 if (freq == gmu->gpu_freqs[perf_index])
102 break;
103
104 __a6xx_gmu_set_freq(gmu, perf_index);
105}
106
107unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu)
108{
109 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
110 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
111 struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
112
113 return gmu->freq;
82} 114}
83 115
84static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu) 116static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu)
@@ -637,7 +669,7 @@ int a6xx_gmu_reset(struct a6xx_gpu *a6xx_gpu)
637 ret = a6xx_hfi_start(gmu, GMU_COLD_BOOT); 669 ret = a6xx_hfi_start(gmu, GMU_COLD_BOOT);
638 670
639 /* Set the GPU back to the highest power frequency */ 671 /* Set the GPU back to the highest power frequency */
640 a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1); 672 __a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
641 673
642out: 674out:
643 if (ret) 675 if (ret)
@@ -676,7 +708,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
676 ret = a6xx_hfi_start(gmu, status); 708 ret = a6xx_hfi_start(gmu, status);
677 709
678 /* Set the GPU to the highest power frequency */ 710 /* Set the GPU to the highest power frequency */
679 a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1); 711 __a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
680 712
681out: 713out:
682 /* Make sure to turn off the boot OOB request on error */ 714 /* Make sure to turn off the boot OOB request on error */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index f34630c72c4d..35f765afae45 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -74,6 +74,8 @@ struct a6xx_gmu {
74 unsigned long gmu_freqs[4]; 74 unsigned long gmu_freqs[4];
75 u32 cx_arc_votes[4]; 75 u32 cx_arc_votes[4];
76 76
77 unsigned long freq;
78
77 struct a6xx_hfi_queue queues[2]; 79 struct a6xx_hfi_queue queues[2];
78 80
79 struct tasklet_struct hfi_tasklet; 81 struct tasklet_struct hfi_tasklet;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 5f36b8d88240..e4ac95f20ca7 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -7,6 +7,8 @@
7#include "a6xx_gpu.h" 7#include "a6xx_gpu.h"
8#include "a6xx_gmu.xml.h" 8#include "a6xx_gmu.xml.h"
9 9
10#include <linux/devfreq.h>
11
10static inline bool _a6xx_check_idle(struct msm_gpu *gpu) 12static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
11{ 13{
12 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 14 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -682,6 +684,8 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
682 684
683 gpu->needs_hw_init = true; 685 gpu->needs_hw_init = true;
684 686
687 msm_gpu_resume_devfreq(gpu);
688
685 return ret; 689 return ret;
686} 690}
687 691
@@ -690,6 +694,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
690 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 694 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
691 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); 695 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
692 696
697 devfreq_suspend_device(gpu->devfreq.devfreq);
698
693 /* 699 /*
694 * Make sure the GMU is idle before continuing (because some transitions 700 * Make sure the GMU is idle before continuing (because some transitions
695 * may use VBIF 701 * may use VBIF
@@ -753,6 +759,24 @@ static void a6xx_destroy(struct msm_gpu *gpu)
753 kfree(a6xx_gpu); 759 kfree(a6xx_gpu);
754} 760}
755 761
762static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu)
763{
764 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
765 struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
766 u64 busy_cycles;
767 unsigned long busy_time;
768
769 busy_cycles = gmu_read64(&a6xx_gpu->gmu,
770 REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L,
771 REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H);
772
773 busy_time = ((busy_cycles - gpu->devfreq.busy_cycles) * 10) / 192;
774
775 gpu->devfreq.busy_cycles = busy_cycles;
776
777 return busy_time;
778}
779
756static const struct adreno_gpu_funcs funcs = { 780static const struct adreno_gpu_funcs funcs = {
757 .base = { 781 .base = {
758 .get_param = adreno_get_param, 782 .get_param = adreno_get_param,
@@ -768,6 +792,9 @@ static const struct adreno_gpu_funcs funcs = {
768#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) 792#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
769 .show = a6xx_show, 793 .show = a6xx_show,
770#endif 794#endif
795 .gpu_busy = a6xx_gpu_busy,
796 .gpu_get_freq = a6xx_gmu_get_freq,
797 .gpu_set_freq = a6xx_gmu_set_freq,
771 }, 798 },
772 .get_timestamp = a6xx_get_timestamp, 799 .get_timestamp = a6xx_get_timestamp,
773}; 800};
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index dd69e5b0e692..4127dcebc202 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -56,5 +56,6 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
56 56
57int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node); 57int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
58void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu); 58void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
59 59void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq);
60unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu);
60#endif /* __A6XX_GPU_H__ */ 61#endif /* __A6XX_GPU_H__ */