From patchwork Thu Aug 23 09:18:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sharat Masetty X-Patchwork-Id: 10573643 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 56F95112E for ; Thu, 23 Aug 2018 09:19:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 54B222BB06 for ; Thu, 23 Aug 2018 09:19:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 489AD2BAEF; Thu, 23 Aug 2018 09:19:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id CE27B290E0 for ; Thu, 23 Aug 2018 09:18:59 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0A7816E4FC; Thu, 23 Aug 2018 09:18:57 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.29.96]) by gabe.freedesktop.org (Postfix) with ESMTPS id D94106E037; Thu, 23 Aug 2018 09:18:55 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 7883F60594; Thu, 23 Aug 2018 09:18:55 +0000 (UTC) Received: from smasetty-linux.qualcomm.com (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: smasetty@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id A92A8606FA; Thu, 23 Aug 2018 09:18:51 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org A92A8606FA From: Sharat Masetty To: freedreno@lists.freedesktop.org Subject: [PATCH 5/5] drm/msm/A6x: Add devfreq support in A6x Date: Thu, 23 Aug 2018 14:48:31 +0530 Message-Id: <1535015911-2040-6-git-send-email-smasetty@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1535015911-2040-1-git-send-email-smasetty@codeaurora.org> References: <1535015911-2040-1-git-send-email-smasetty@codeaurora.org> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-arm-msm@vger.kernel.org, Sharat Masetty , dri-devel@lists.freedesktop.org MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Implement routines to estimate GPU busy time and fetching the current frequency for the polling interval. This is required by the devfreq framework which recommends a frequency change if needed. The driver code then tries to set this new frequency on the GPU by sending an Out Of Band(OOB) request. Signed-off-by: Sharat Masetty --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 46 +++++++++++++++++++++++++++++++---- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 2 ++ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 27 ++++++++++++++++++++ drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 2 ++ 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index f6634c0..92ff48b 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -67,8 +67,10 @@ static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu) A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF)); } -static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) +static int __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) { + int ret; + gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0); gmu_write(gmu, REG_A6XX_GMU_DCVS_PERF_SETTING, @@ -84,7 +86,41 @@ static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) a6xx_gmu_set_oob(gmu, GMU_OOB_DCVS_SET); a6xx_gmu_clear_oob(gmu, GMU_OOB_DCVS_SET); - return gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN); + ret = gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN); + if (!ret) + gmu->cur_freq = gmu->gpu_freqs[index]; + + return ret; +} + +int a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + struct a6xx_gmu *gmu = &a6xx_gpu->gmu; + u32 perf_index = 0; + + if (freq == gmu->cur_freq) + return 0; + + //TODO: Use a hashmap instead? This gets called potentially every ~10 ms + for (perf_index = 0; perf_index < gmu->nr_gpu_freqs; perf_index++) + if (freq == gmu->gpu_freqs[perf_index]) + break; + + if (perf_index == gmu->nr_gpu_freqs) + return -EINVAL; + + return __a6xx_gmu_set_freq(gmu, perf_index); +} + +unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + struct a6xx_gmu *gmu = &a6xx_gpu->gmu; + + return gmu->cur_freq; } static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu) @@ -629,8 +665,8 @@ int a6xx_gmu_reset(struct a6xx_gpu *a6xx_gpu) if (!ret) ret = a6xx_hfi_start(gmu, GMU_COLD_BOOT); - /* Set the GPU back to the highest power frequency */ - a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1); + /* Save the current frequency for devfreq */ + gmu->cur_freq = gmu->gpu_freqs[gmu->nr_gpu_freqs - 1]; out: if (ret) @@ -671,7 +707,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) ret = a6xx_hfi_start(gmu, status); /* Set the GPU to the highest power frequency */ - a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1); + __a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1); out: /* 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 f9e4dfe..ce6e5ca 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -77,6 +77,8 @@ struct a6xx_gmu { unsigned long gmu_freqs[4]; u32 cx_arc_votes[4]; + unsigned long cur_freq; + struct a6xx_hfi_queue queues[2]; 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 3429d33a..af90706 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -7,6 +7,8 @@ #include "a6xx_gpu.h" #include "a6xx_gmu.xml.h" +#include + static inline bool _a6xx_check_idle(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -682,6 +684,8 @@ static int a6xx_pm_resume(struct msm_gpu *gpu) gpu->needs_hw_init = true; + msm_gpu_resume_devfreq(gpu); + return ret; } @@ -690,6 +694,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu) struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + devfreq_suspend_device(gpu->devfreq.devfreq); + /* * Make sure the GMU is idle before continuing (because some transitions * may use VBIF @@ -753,6 +759,24 @@ static void a6xx_destroy(struct msm_gpu *gpu) kfree(a6xx_gpu); } +static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + u64 busy_cycles; + unsigned long busy_time; + + busy_cycles = gmu_read64(&a6xx_gpu->gmu, + REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L, + REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H); + + busy_time = ((busy_cycles - gpu->devfreq.busy_cycles) * 10) / 192; + + gpu->devfreq.busy_cycles = busy_cycles; + + return busy_time; +} + static const struct adreno_gpu_funcs funcs = { .base = { .get_param = adreno_get_param, @@ -768,6 +792,9 @@ static void a6xx_destroy(struct msm_gpu *gpu) #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) .show = a6xx_show, #endif + .gpu_busy = a6xx_gpu_busy, + .gpu_get_freq = a6xx_gmu_get_freq, + .gpu_set_freq = a6xx_gmu_set_freq, }, .get_timestamp = a6xx_get_timestamp, }; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index 32c2501..f236767 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h @@ -56,5 +56,7 @@ struct a6xx_gpu { int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node, struct platform_device *gpu_pdev); void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu); +int a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq); +unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu); #endif /* __A6XX_GPU_H__ */