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

drm/msm/adreno: Use OPP for every GPU generation

Some older GPUs (namely a2xx with no opp tables at all and a320 with
downstream-remnants gpu pwrlevels) used not to have OPP tables. They
both however had just one frequency defined, making it extremely easy
to construct such an OPP table from within the driver if need be.

Do so and switch all clk_set_rate calls on core_clk to their OPP
counterparts.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Patchwork: https://patchwork.freedesktop.org/patch/523784/
Link: https://lore.kernel.org/r/20230223-topic-opp-v3-3-5f22163cd1df@linaro.org
Signed-off-by: Rob Clark <robdclark@chromium.org>

authored by

Konrad Dybcio and committed by
Rob Clark
9f251f93 c11fa120

+47 -58
+44 -55
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 922 922 ring->id); 923 923 } 924 924 925 - /* Get legacy powerlevels from qcom,gpu-pwrlevels and populate the opp table */ 926 - static int adreno_get_legacy_pwrlevels(struct device *dev) 927 - { 928 - struct device_node *child, *node; 929 - int ret; 930 - 931 - node = of_get_compatible_child(dev->of_node, "qcom,gpu-pwrlevels"); 932 - if (!node) { 933 - DRM_DEV_DEBUG(dev, "Could not find the GPU powerlevels\n"); 934 - return -ENXIO; 935 - } 936 - 937 - for_each_child_of_node(node, child) { 938 - unsigned int val; 939 - 940 - ret = of_property_read_u32(child, "qcom,gpu-freq", &val); 941 - if (ret) 942 - continue; 943 - 944 - /* 945 - * Skip the intentionally bogus clock value found at the bottom 946 - * of most legacy frequency tables 947 - */ 948 - if (val != 27000000) 949 - dev_pm_opp_add(dev, val, 0); 950 - } 951 - 952 - of_node_put(node); 953 - 954 - return 0; 955 - } 956 - 957 - static void adreno_get_pwrlevels(struct device *dev, 925 + static int adreno_get_pwrlevels(struct device *dev, 958 926 struct msm_gpu *gpu) 959 927 { 928 + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 960 929 unsigned long freq = ULONG_MAX; 961 930 struct dev_pm_opp *opp; 962 931 int ret; 963 932 964 933 gpu->fast_rate = 0; 965 934 966 - /* You down with OPP? */ 967 - if (!of_find_property(dev->of_node, "operating-points-v2", NULL)) 968 - ret = adreno_get_legacy_pwrlevels(dev); 969 - else { 970 - ret = devm_pm_opp_of_add_table(dev); 971 - if (ret) 972 - DRM_DEV_ERROR(dev, "Unable to set the OPP table\n"); 973 - } 974 - 975 - if (!ret) { 976 - /* Find the fastest defined rate */ 977 - opp = dev_pm_opp_find_freq_floor(dev, &freq); 978 - if (!IS_ERR(opp)) { 979 - gpu->fast_rate = freq; 980 - dev_pm_opp_put(opp); 935 + /* devm_pm_opp_of_add_table may error out but will still create an OPP table */ 936 + ret = devm_pm_opp_of_add_table(dev); 937 + if (ret == -ENODEV) { 938 + /* Special cases for ancient hw with ancient DT bindings */ 939 + if (adreno_is_a2xx(adreno_gpu)) { 940 + dev_warn(dev, "Unable to find the OPP table. Falling back to 200 MHz.\n"); 941 + dev_pm_opp_add(dev, 200000000, 0); 942 + } else if (adreno_is_a320(adreno_gpu)) { 943 + dev_warn(dev, "Unable to find the OPP table. Falling back to 450 MHz.\n"); 944 + dev_pm_opp_add(dev, 450000000, 0); 945 + } else { 946 + DRM_DEV_ERROR(dev, "Unable to find the OPP table\n"); 947 + return -ENODEV; 981 948 } 949 + } else if (ret) { 950 + DRM_DEV_ERROR(dev, "Unable to set the OPP table\n"); 951 + return ret; 982 952 } 983 953 984 - if (!gpu->fast_rate) { 985 - dev_warn(dev, 986 - "Could not find a clock rate. Using a reasonable default\n"); 987 - /* Pick a suitably safe clock speed for any target */ 988 - gpu->fast_rate = 200000000; 989 - } 954 + /* Find the fastest defined rate */ 955 + opp = dev_pm_opp_find_freq_floor(dev, &freq); 956 + if (IS_ERR(opp)) 957 + return PTR_ERR(opp); 958 + 959 + gpu->fast_rate = freq; 960 + dev_pm_opp_put(opp); 990 961 991 962 DBG("fast_rate=%u, slow_rate=27000000", gpu->fast_rate); 963 + 964 + return 0; 992 965 } 993 966 994 967 int adreno_gpu_ocmem_init(struct device *dev, struct adreno_gpu *adreno_gpu, ··· 1019 1046 struct adreno_rev *rev = &config->rev; 1020 1047 const char *gpu_name; 1021 1048 u32 speedbin; 1049 + int ret; 1050 + 1051 + /* 1052 + * This can only be done before devm_pm_opp_of_add_table(), or 1053 + * dev_pm_opp_set_config() will WARN_ON() 1054 + */ 1055 + if (IS_ERR(devm_clk_get(dev, "core"))) { 1056 + /* 1057 + * If "core" is absent, go for the legacy clock name. 1058 + * If we got this far in probing, it's a given one of them exists. 1059 + */ 1060 + devm_pm_opp_set_clkname(dev, "core_clk"); 1061 + } else 1062 + devm_pm_opp_set_clkname(dev, "core"); 1022 1063 1023 1064 adreno_gpu->funcs = funcs; 1024 1065 adreno_gpu->info = adreno_info(config->rev); ··· 1057 1070 1058 1071 adreno_gpu_config.nr_rings = nr_rings; 1059 1072 1060 - adreno_get_pwrlevels(dev, gpu); 1073 + ret = adreno_get_pwrlevels(dev, gpu); 1074 + if (ret) 1075 + return ret; 1061 1076 1062 1077 pm_runtime_set_autosuspend_delay(dev, 1063 1078 adreno_gpu->info->inactive_period);
+2 -2
drivers/gpu/drm/msm/msm_gpu.c
··· 58 58 static int enable_clk(struct msm_gpu *gpu) 59 59 { 60 60 if (gpu->core_clk && gpu->fast_rate) 61 - clk_set_rate(gpu->core_clk, gpu->fast_rate); 61 + dev_pm_opp_set_rate(&gpu->pdev->dev, gpu->fast_rate); 62 62 63 63 /* Set the RBBM timer rate to 19.2Mhz */ 64 64 if (gpu->rbbmtimer_clk) ··· 77 77 * will be rounded down to zero anyway so it all works out. 78 78 */ 79 79 if (gpu->core_clk) 80 - clk_set_rate(gpu->core_clk, 27000000); 80 + dev_pm_opp_set_rate(&gpu->pdev->dev, 27000000); 81 81 82 82 if (gpu->rbbmtimer_clk) 83 83 clk_set_rate(gpu->rbbmtimer_clk, 0);
+1 -1
drivers/gpu/drm/msm/msm_gpu_devfreq.c
··· 48 48 gpu->funcs->gpu_set_freq(gpu, opp, df->suspended); 49 49 mutex_unlock(&df->lock); 50 50 } else { 51 - clk_set_rate(gpu->core_clk, *freq); 51 + dev_pm_opp_set_rate(dev, *freq); 52 52 } 53 53 54 54 dev_pm_opp_put(opp);