Commit fcf9d0b7 authored by Jordan Crouse's avatar Jordan Crouse Committed by Greg Kroah-Hartman

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: default avatarJordan Crouse <jcrouse@codeaurora.org>
Acked-by: default avatarRob Clark <robdclark@gmail.com>
Reviewed-by: default avatarEvan Green <evgreen@chromium.org>
Signed-off-by: default avatarGeorgi Djakov <georgi.djakov@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 682a6044
...@@ -5,6 +5,7 @@ config DRM_MSM ...@@ -5,6 +5,7 @@ config DRM_MSM
depends on ARCH_QCOM || SOC_IMX5 || (ARM && COMPILE_TEST) depends on ARCH_QCOM || SOC_IMX5 || (ARM && COMPILE_TEST)
depends on OF && COMMON_CLK depends on OF && COMMON_CLK
depends on MMU depends on MMU
depends on INTERCONNECT || !INTERCONNECT
select QCOM_MDT_LOADER if ARCH_QCOM select QCOM_MDT_LOADER if ARCH_QCOM
select REGULATOR select REGULATOR
select DRM_KMS_HELPER select DRM_KMS_HELPER
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */ /* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/interconnect.h>
#include <linux/pm_opp.h> #include <linux/pm_opp.h>
#include <soc/qcom/cmd-db.h> #include <soc/qcom/cmd-db.h>
...@@ -84,6 +85,9 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu) ...@@ -84,6 +85,9 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
{ {
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct msm_gpu *gpu = &adreno_gpu->base;
int ret; int ret;
gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0); gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0);
...@@ -106,6 +110,12 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) ...@@ -106,6 +110,12 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret); dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
gmu->freq = gmu->gpu_freqs[index]; gmu->freq = gmu->gpu_freqs[index];
/*
* Eventually we will want to scale the path vote with the frequency but
* for now leave it at max so that the performance is nominal.
*/
icc_set_bw(gpu->icc_path, 0, MBps_to_icc(7216));
} }
void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq) void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
...@@ -705,6 +715,8 @@ int a6xx_gmu_reset(struct a6xx_gpu *a6xx_gpu) ...@@ -705,6 +715,8 @@ int a6xx_gmu_reset(struct a6xx_gpu *a6xx_gpu)
int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
{ {
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct msm_gpu *gpu = &adreno_gpu->base;
struct a6xx_gmu *gmu = &a6xx_gpu->gmu; struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
int status, ret; int status, ret;
...@@ -720,6 +732,9 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) ...@@ -720,6 +732,9 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
if (ret) if (ret)
goto out; goto out;
/* Set the bus quota to a reasonable value for boot */
icc_set_bw(gpu->icc_path, 0, MBps_to_icc(3072));
a6xx_gmu_irq_enable(gmu); a6xx_gmu_irq_enable(gmu);
/* Check to see if we are doing a cold or warm boot */ /* Check to see if we are doing a cold or warm boot */
...@@ -760,6 +775,8 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu) ...@@ -760,6 +775,8 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu)
int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu) int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
{ {
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct msm_gpu *gpu = &adreno_gpu->base;
struct a6xx_gmu *gmu = &a6xx_gpu->gmu; struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
u32 val; u32 val;
...@@ -806,6 +823,9 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu) ...@@ -806,6 +823,9 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
/* Tell RPMh to power off the GPU */ /* Tell RPMh to power off the GPU */
a6xx_rpmh_stop(gmu); a6xx_rpmh_stop(gmu);
/* Remove the bus vote */
icc_set_bw(gpu->icc_path, 0, 0);
clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks); clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);
pm_runtime_put_sync(gmu->dev); pm_runtime_put_sync(gmu->dev);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
#include <linux/ascii85.h> #include <linux/ascii85.h>
#include <linux/interconnect.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pm_opp.h> #include <linux/pm_opp.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -747,6 +748,11 @@ static int adreno_get_pwrlevels(struct device *dev, ...@@ -747,6 +748,11 @@ static int adreno_get_pwrlevels(struct device *dev,
DBG("fast_rate=%u, slow_rate=27000000", gpu->fast_rate); DBG("fast_rate=%u, slow_rate=27000000", gpu->fast_rate);
/* Check for an interconnect path for the bus */
gpu->icc_path = of_icc_get(dev, NULL);
if (IS_ERR(gpu->icc_path))
gpu->icc_path = NULL;
return 0; return 0;
} }
...@@ -787,10 +793,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, ...@@ -787,10 +793,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu) void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)
{ {
struct msm_gpu *gpu = &adreno_gpu->base;
unsigned int i; unsigned int i;
for (i = 0; i < ARRAY_SIZE(adreno_gpu->info->fw); i++) for (i = 0; i < ARRAY_SIZE(adreno_gpu->info->fw); i++)
release_firmware(adreno_gpu->fw[i]); release_firmware(adreno_gpu->fw[i]);
icc_put(gpu->icc_path);
msm_gpu_cleanup(&adreno_gpu->base); msm_gpu_cleanup(&adreno_gpu->base);
} }
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define __MSM_GPU_H__ #define __MSM_GPU_H__
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/interconnect.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include "msm_drv.h" #include "msm_drv.h"
...@@ -118,6 +119,8 @@ struct msm_gpu { ...@@ -118,6 +119,8 @@ struct msm_gpu {
struct clk *ebi1_clk, *core_clk, *rbbmtimer_clk; struct clk *ebi1_clk, *core_clk, *rbbmtimer_clk;
uint32_t fast_rate; uint32_t fast_rate;
struct icc_path *icc_path;
/* Hang and Inactivity Detection: /* Hang and Inactivity Detection:
*/ */
#define DRM_MSM_INACTIVE_PERIOD 66 /* in ms (roughly four frames) */ #define DRM_MSM_INACTIVE_PERIOD 66 /* in ms (roughly four frames) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment