Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm/a6xx: Add support for an interconnect path

Try to get the interconnect path for the GPU and vote for the maximum
bandwidth to support all frequencies. This is needed for performance.
Later we will want to scale the bandwidth based on the frequency to
also optimize for power but that will require some device tree
infrastructure that does not yet exist.

v6: use icc_set_bw() instead of icc_set()
v5: Remove hardcoded interconnect name and just use the default
v4: Don't use a port string at all to skip the need for names in the DT
v3: Use macros and change port string per Georgi Djakov

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Acked-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Evan Green <evgreen@chromium.org>
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Jordan Crouse and committed by
Greg Kroah-Hartman
fcf9d0b7 682a6044

+33
+1
drivers/gpu/drm/msm/Kconfig
··· 5 5 depends on ARCH_QCOM || SOC_IMX5 || (ARM && COMPILE_TEST) 6 6 depends on OF && COMMON_CLK 7 7 depends on MMU 8 + depends on INTERCONNECT || !INTERCONNECT 8 9 select QCOM_MDT_LOADER if ARCH_QCOM 9 10 select REGULATOR 10 11 select DRM_KMS_HELPER
+20
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
··· 2 2 /* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */ 3 3 4 4 #include <linux/clk.h> 5 + #include <linux/interconnect.h> 5 6 #include <linux/pm_opp.h> 6 7 #include <soc/qcom/cmd-db.h> 7 8 ··· 85 84 86 85 static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) 87 86 { 87 + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); 88 + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 89 + struct msm_gpu *gpu = &adreno_gpu->base; 88 90 int ret; 89 91 90 92 gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0); ··· 110 106 dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret); 111 107 112 108 gmu->freq = gmu->gpu_freqs[index]; 109 + 110 + /* 111 + * Eventually we will want to scale the path vote with the frequency but 112 + * for now leave it at max so that the performance is nominal. 113 + */ 114 + icc_set_bw(gpu->icc_path, 0, MBps_to_icc(7216)); 113 115 } 114 116 115 117 void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq) ··· 715 705 716 706 int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) 717 707 { 708 + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 709 + struct msm_gpu *gpu = &adreno_gpu->base; 718 710 struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 719 711 int status, ret; 720 712 ··· 731 719 ret = clk_bulk_prepare_enable(gmu->nr_clocks, gmu->clocks); 732 720 if (ret) 733 721 goto out; 722 + 723 + /* Set the bus quota to a reasonable value for boot */ 724 + icc_set_bw(gpu->icc_path, 0, MBps_to_icc(3072)); 734 725 735 726 a6xx_gmu_irq_enable(gmu); 736 727 ··· 775 760 776 761 int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu) 777 762 { 763 + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 764 + struct msm_gpu *gpu = &adreno_gpu->base; 778 765 struct a6xx_gmu *gmu = &a6xx_gpu->gmu; 779 766 u32 val; 780 767 ··· 822 805 823 806 /* Tell RPMh to power off the GPU */ 824 807 a6xx_rpmh_stop(gmu); 808 + 809 + /* Remove the bus vote */ 810 + icc_set_bw(gpu->icc_path, 0, 0); 825 811 826 812 clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks); 827 813
+9
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 18 18 */ 19 19 20 20 #include <linux/ascii85.h> 21 + #include <linux/interconnect.h> 21 22 #include <linux/kernel.h> 22 23 #include <linux/pm_opp.h> 23 24 #include <linux/slab.h> ··· 748 747 749 748 DBG("fast_rate=%u, slow_rate=27000000", gpu->fast_rate); 750 749 750 + /* Check for an interconnect path for the bus */ 751 + gpu->icc_path = of_icc_get(dev, NULL); 752 + if (IS_ERR(gpu->icc_path)) 753 + gpu->icc_path = NULL; 754 + 751 755 return 0; 752 756 } 753 757 ··· 793 787 794 788 void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu) 795 789 { 790 + struct msm_gpu *gpu = &adreno_gpu->base; 796 791 unsigned int i; 797 792 798 793 for (i = 0; i < ARRAY_SIZE(adreno_gpu->info->fw); i++) 799 794 release_firmware(adreno_gpu->fw[i]); 795 + 796 + icc_put(gpu->icc_path); 800 797 801 798 msm_gpu_cleanup(&adreno_gpu->base); 802 799 }
+3
drivers/gpu/drm/msm/msm_gpu.h
··· 19 19 #define __MSM_GPU_H__ 20 20 21 21 #include <linux/clk.h> 22 + #include <linux/interconnect.h> 22 23 #include <linux/regulator/consumer.h> 23 24 24 25 #include "msm_drv.h" ··· 118 117 int nr_clocks; 119 118 struct clk *ebi1_clk, *core_clk, *rbbmtimer_clk; 120 119 uint32_t fast_rate; 120 + 121 + struct icc_path *icc_path; 121 122 122 123 /* Hang and Inactivity Detection: 123 124 */